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

Как сделать так, чтобы значения экземпляров класса не повторялись - C++

Восстановить пароль Регистрация
 
лилиэн
6 / 6 / 0
Регистрация: 22.11.2012
Сообщений: 95
30.04.2014, 15:09     Как сделать так, чтобы значения экземпляров класса не повторялись #1
Я пытаюсь написать игру 2048.
Коротко об игре, для тех кто не знает:
Есть поле 4х4 в нем появляются на случайной позиции квадратики с значением 2 или 4, используя клавиши вправо,влево,вверх,вниз то эти квадратики перемещаются в заданном направлении,если два квадратика с одинаковым значением столкнутся,то они сольются в единый квадрат с значением в 2 раза больше.
При каждом движении, появляется новый квадрат на случайном, пустом месте.
Игра продолжается, пока есть свободные места, и есть движения.

Для этих "квадратиков" я сделала класс
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Rect
{
public:
    int x;//позиция по х
    int y;//позиция по y
    int value;//значение в квадрате
    static int id;//количество существующих квадратов
    int myid;//номер квадрата
    Rect();//конструктор(в котором кстате и есть вся проблема)
    Rect(const Rect &copy);
    ~Rect();
    void AddRects(int direction);
};
int Rect::id=0;
Rect *rectangles[16];


Я создала массив указателей, и при каждом движении создаю новый квадратик.
Вот конструктор
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Rect::Rect()
{
    id++;
    this->myid=id;
    this->x=rand()%4;
    this->y=rand()%4;
    /*for(int i=0;i<id;i++)
    {
        if((rectangles[i]->x==this->x)&&(rectangles[i]->y==this->y)&&(rectangles[i]->myid!=this->myid))
        {
            this->x=rand()%4;
            this->y=rand()%4;
        }
 
    }*/
 
    this->value=rand()%10;
    if(this->value==9)
        this->value=2;
    else
        this->value=4;
    glRectf(60+this->x*50,60+this->y*50,90+this->x*50,90+this->y*50);
}

Псевдослучайно я генерирую позицию квадрата, и затем рисую его, все хорошо, но когда добавляю код проверки наличи другого квадрата ,на той позиции программа завершается.
(код закоментирован)

В чем может быть проблема? Сначала, проблема была в том, что я проверяла равенство координат квадрата самим с собой, и они были одинаковые, и менялись, снова проверялись, и так по кругу, но я добавила проверку, если id нашего и проверяемого квадрата одинаковые они игнорируются..

Надеюсь я не запутала все....
В общем, как мне сделать проверку того, не появляется ли квадрат на том же месте что занято
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.04.2014, 15:09     Как сделать так, чтобы значения экземпляров класса не повторялись
Посмотрите здесь:

C++ Сгенерировать одномерный масив так чтобы цифры в нём не повторялись
Сделать так, чтобы при вводе отрицательного значения программа выводила errror C++
C++ создать Объединение двух одномерных массивов в один НО так ,чтобы елементи в повторялись
C++ Как сделать так, чтобы функция rand() возвращала разные значения
C++ Объединить два массива так, чтобы числа в новом массиве не повторялись
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
SHLAKBAUM
22 / 22 / 7
Регистрация: 29.09.2013
Сообщений: 51
30.04.2014, 18:02     Как сделать так, чтобы значения экземпляров класса не повторялись #2
Конечно неплохо бы весь код, но так, навскидку, могу предположить, что вы обращаетесь в цикле к несуществующему объекту, т.к. наверняка при объединении двух клеток одну их них вы удаляете или что-то вроде того.
stima
430 / 285 / 16
Регистрация: 22.03.2011
Сообщений: 929
Завершенные тесты: 1
30.04.2014, 18:11     Как сделать так, чтобы значения экземпляров класса не повторялись #3
У Вас класический сегфолт. Чтобы решить его вы должны ответить на два вопроса:
1. Удаляется ли Rect из определенной позиции масива rectangle? Смещаются ли при этом указатели других Rect?
2. Сначала Вы увеличиваете "id++", но не записываете при этом новый Rect в массив, но при этом итеруруетесь до увеличенного "id".

Кликните здесь для просмотра всего текста

1. Решением является использование контейнеров.
2. "грамотным решением" ялвется использование "позиционного поля".
лилиэн
6 / 6 / 0
Регистрация: 22.11.2012
Сообщений: 95
30.04.2014, 21:22  [ТС]     Как сделать так, чтобы значения экземпляров класса не повторялись #4
Дело в том, что я только начала писать. Еще нету почти ничего. Проверка идет от 0 до id, тоесть проверяются только те, которые существуют.
Кода отвечающего за перемещение и за слияние и соответсвенно удаление еще нету, есть только появляющиеся прямоугольники и все. И задача на данном этапе обеспечить только то, чтобы они появлялись на разных местах, и все.
Весь код привожу ниже
Кликните здесь для просмотра всего текста
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include<GL/glut.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
int ClientWidth=300;
int ClientHeigh=400;
int forbitten=50,forbitten2=250;
class Rect
{
public:
    int x;
    int y;
    int value;
    static int id;
    int myid;
    Rect();
    Rect(const Rect &copy);
    ~Rect();
    void AddRects(int direction);
};
int Rect::id=0;
Rect *rectangles[16];
void RenderScene(void)
    {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0f,0.0f,0.0f);
    glLineWidth(5);
    glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
    glEnable(GL_LINE_SMOOTH);
    glBegin(GL_LINES);
        for(int i=1;i<=5;i++)
        {
        glVertex2f(50,i*50);
        glVertex2f(250,i*50);
        }
        for(int i=1;i<=5;i++)
        {
        glVertex2f(i*50,50);
        glVertex2f(i*50,250);
        }
    glEnd();
    glLineWidth(1);
    glBegin(GL_LINES);
        glVertex2f(50,50-11);
        glVertex2f(250,50-11);
        glVertex2f(50,250+11);
        glVertex2f(250,250+11);
        glVertex2f(50-11,50);
        glVertex2f(50-11,250);
        glVertex2f(250+11,50);
        glVertex2f(250+11,250);
    glEnd();
    glPointSize(25);
    glBegin(GL_POINTS);
    glVertex2f(50,50);
    glVertex2f(50,250);
    glVertex2f(250,50);
    glVertex2f(250,250);
    glEnd();
    rectangles[0]=new Rect;
    glutSwapBuffers();
    }
 
 
void SetupRC()
    {
    glClearColor(0.94f, 0.78f, 0.49f, 1.0f );
    glColor3f(0.0f, 1.0f, 0.0f);
    }
void SpecialKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
 
    if(key == GLUT_KEY_DOWN)
 
    if(key == GLUT_KEY_LEFT)
 
    if(key == GLUT_KEY_RIGHT)
 
    glutPostRedisplay();
    }
 
 
void ChangeSize(int w, int h)
    {
    GLfloat nRange = 300.0f;
    if(h == 0)
        h = 1;
 
    glViewport(0, 0, w, h);
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
 
    if (w <= h) 
        gluOrtho2D (0, nRange, 0, nRange+100);
    else 
        gluOrtho2D(0, nRange, 0, nRange+100);
 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }
 
int main(int argc, char* argv[])
    {
        srand(time(NULL));
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(ClientWidth,ClientHeigh);
    glutCreateWindow("Lilian Su 2048 Game");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
    SetupRC();
    glutMainLoop();
 
    return 0;
    }
Rect::Rect()
{
    id++;
    this->myid=id;
    this->x=rand()%4;
    this->y=rand()%4;
    /*for(int i=0;i<id;i++)
    {
        if((rectangles[i]->x==this->x)&&(rectangles[i]->y==this->y)&&(rectangles[i]->myid!=this->myid))
        {
            this->x=rand()%4;
            this->y=rand()%4;
        }
 
    }*/
 
    this->value=rand()%10;
    if(this->value==9)
        this->value=2;
    else
        this->value=4;
    glRectf(60+this->x*50,60+this->y*50,90+this->x*50,90+this->y*50);
}


Добавлено через 56 секунд
А что за позиционное поле, загуглила но кажись не то что вы имели в виду...
stima
430 / 285 / 16
Регистрация: 22.03.2011
Сообщений: 929
Завершенные тесты: 1
30.04.2014, 22:00     Как сделать так, чтобы значения экземпляров класса не повторялись #5
1. Подумайте над этой строчкой
Цитата Сообщение от лилиэн Посмотреть сообщение
glEnd();
* * rectangles[0]=new Rect;
* * glutSwapBuffers();
2. Смотрите, у Вас есть игровое поле (матрица) фиксированного размера. Зачем Вам линейно (в цикле) проходить по всем элементам и сравнивать их координаты, если можно по данным координатам проверить есть ли элемент или нет?
RQdan
65 / 65 / 17
Регистрация: 26.10.2013
Сообщений: 198
30.04.2014, 22:32     Как сделать так, чтобы значения экземпляров класса не повторялись #6
Цитата Сообщение от лилиэн Посмотреть сообщение
if((rectangles[i]->x==this->x)&&(rectangles[i]->y==this->y)&&(rectangles[i]->myid!=this->myid))
У Вас в массиве указателей элементы не инициализированы, а Вы пытаетесь взять из них данные - соответственно возникает ошибка. Попробуйте при запуске программы сначала инициализировать массив, причем пустые ячейки будут иметь определенные значения, например x=-1,y=-1, myid=-1.
stima
430 / 285 / 16
Регистрация: 22.03.2011
Сообщений: 929
Завершенные тесты: 1
30.04.2014, 22:36     Как сделать так, чтобы значения экземпляров класса не повторялись #7
RQdan, не "относится" к вопросу.
RQdan
65 / 65 / 17
Регистрация: 26.10.2013
Сообщений: 198
30.04.2014, 23:07     Как сделать так, чтобы значения экземпляров класса не повторялись #8
Цитата Сообщение от RQdan Посмотреть сообщение
У Вас в массиве указателей элементы не инициализированы, а Вы пытаетесь взять из них данные - соответственно возникает ошибка. Попробуйте при запуске программы сначала инициализировать массив, причем пустые ячейки будут иметь определенные значения, например x=-1,y=-1, myid=-1.
Не разобрался в вопросе, думал, что массив описывает ячейки на поле. Так что не подходит ответ.
лилиэн
6 / 6 / 0
Регистрация: 22.11.2012
Сообщений: 95
01.05.2014, 10:28  [ТС]     Как сделать так, чтобы значения экземпляров класса не повторялись #9
Цитата Сообщение от stima Посмотреть сообщение
2. Смотрите, у Вас есть игровое поле (матрица) фиксированного размера. Зачем Вам линейно (в цикле) проходить по всем элементам и сравнивать их координаты, если можно по данным координатам проверить есть ли элемент или нет?
Тоесть, если я правельно понимаю у меня есть отдельно поле попустим
C++
1
bool Field[4][4]
и когда я создаю элемент, то я отмечаю есть он на поле или нет
C++
1
2
3
4
5
6
7
this->x=rand()%4;
this->y=rand()%4;
while(Field[this->x][this->y])
    {
        this->x=rand()%4;
        this->y=rand()%4;
    }
Как то так?
Или же поле должно полностью заменить класс Rect?
что то вроде
C++
1
2
3
4
5
6
7
class GameField
{
   private:
     bool FieldState[4][4];//есть ли элемент на клетке
     int FieldValue[4][4];//значение элемента на клетке (-1 если нету)
//всякие там методы
};
И реализовать всю механику в виде методов класса?

Добавлено через 53 минуты
Значит я переделала глобально логику.
Есть
GameField.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<time.h>
#include<stdlib.h>
#include<GL/glut.h>
 
class GameField
{
    private:
        bool FieldState[4][4];
        int  FieldValue[4][4];
        bool NoMoves;
        void CreateNewRect();
    public:
        GameField();
        ~GameField();
        void PerformMove(int direction);
        bool CheckForMoves();
        void RedrawField();
};

GameField.cpp
Кликните здесь для просмотра всего текста
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
#include"GameField.h"
 
GameField::GameField()
{
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        {
            this->FieldState[i][j]=false;
            this->FieldValue[i][j]=-1;
        }
    this->NoMoves=false;
    CreateNewRect();
    CreateNewRect();
    RedrawField();
}
 
 
GameField::~GameField()
{
}
 
 
void GameField::CreateNewRect()
{
    int x=rand()%4;
    int y=rand()%4;
    while(this->FieldState[x][y])
    {
        int x=rand()%4;
        int y=rand()%4;
    }
    this->FieldState[x][y]=true;
    this->FieldValue[x][y]=rand()%10;
    if(this->FieldValue[x][y]==10)
        this->FieldValue[x][y]=4;
    else
        this->FieldValue[x][y]=2;
 
}
void GameField::RedrawField()
{
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        {
            if(this->FieldState[i][j]==true)
            {
                switch(this->FieldValue[i][j])
                {
                  case 2:
                      glColor3f(1,0,0);
                      break;
                  case 4:
                      glColor3f(0,1,0);
                      break;
                  case 8:
                      glColor3f(0,0,1);
                      break;
                  case 16:
                      glColor3f(0,1,1);
                      break;
                  case 32:
                      glColor3f(1,1,0);
                      break;
                  case 64:
                      glColor3f(1,0,1);
                      break;
                      
                }
            glRectf(60+i*50,60+j*50,90+i*50,90+j*50);
            }
        }
}

ну и соответсвенно MainLoop.cpp
Кликните здесь для просмотра всего текста
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include"GameField.h"
 
int ClientWidth=300;
int ClientHeigh=400;
 
class GameField;
void RenderScene(void); 
void SetupRC();
void SpecialKeys(int key, int x, int y);
void ChangeSize(int w, int h);
 
 
int main(int argc, char* argv[])
    {
    srand(time(NULL));
    GameField MyGameField;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(ClientWidth,ClientHeigh);
    glutCreateWindow("Lilian Su 2048 Game");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
    SetupRC();
    glutMainLoop();
 
    return 0;
    }
void RenderScene(void)
    {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0f,0.0f,0.0f);
    glLineWidth(5);
    glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
    glEnable(GL_LINE_SMOOTH);
    glBegin(GL_LINES);
        for(int i=1;i<=5;i++)
        {
        glVertex2f(50,i*50);
        glVertex2f(250,i*50);
        }
        for(int i=1;i<=5;i++)
        {
        glVertex2f(i*50,50);
        glVertex2f(i*50,250);
        }
    glEnd();
    glLineWidth(1);
    glBegin(GL_LINES);
        glVertex2f(50,50-11);
        glVertex2f(250,50-11);
        glVertex2f(50,250+11);
        glVertex2f(250,250+11);
        glVertex2f(50-11,50);
        glVertex2f(50-11,250);
        glVertex2f(250+11,50);
        glVertex2f(250+11,250);
    glEnd();
    glPointSize(25);
    glBegin(GL_POINTS);
    glVertex2f(50,50);
    glVertex2f(50,250);
    glVertex2f(250,50);
    glVertex2f(250,250);
    glEnd();
    glutSwapBuffers();
    }
void SetupRC()
    {
    glClearColor(0.94f, 0.78f, 0.49f, 1.0f );
    glColor3f(0.0f, 1.0f, 0.0f);
    }
void SpecialKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
    {
    }
 
    if(key == GLUT_KEY_DOWN)
 
    if(key == GLUT_KEY_LEFT)
 
    if(key == GLUT_KEY_RIGHT)
 
    glutPostRedisplay();
    }
void ChangeSize(int w, int h)
    {
    GLfloat nRange = 300.0f;
    if(h == 0)
        h = 1;
 
    glViewport(0, 0, w, h);
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
 
    if (w <= h) 
        gluOrtho2D (0, nRange, 0, nRange+100);
    else 
        gluOrtho2D(0, nRange, 0, nRange+100);
 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }

Проблема теперь следующая.... прямоугольники не рисуются вообще. Это конечно не совсем наверно с++ проблема, а скорее opengl или еще скорее из-за того что я неправильно на файлы разделила..
ведь сама функция отрисовки она в мэйне
C++
1
void RenderScene(void)
а перерисовка поля является методом класса
C++
1
void GameField::RedrawField()
По сути дела ,все рисование должно происходить внутри функции RenderScene но по логике перерисовку поля должны вызывать методы класса( при создании, после каждого хода)
Если же мне вызывать перерисовку напрямую из RenderScene , то как мне контролировать "моменты" когда это надо сделать то?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.05.2014, 19:24     Как сделать так, чтобы значения экземпляров класса не повторялись
Еще ссылки по теме:

Перемешать массив так, чтобы числа в нём не повторялись C++
Сделать так, чтобы функция возвращала как целые, так и дробные значения C++
C++ Рандомное заполнение массива так, чтобы числа в нем не повторялись

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

Или воспользуйтесь поиском по форуму:
stima
430 / 285 / 16
Регистрация: 22.03.2011
Сообщений: 929
Завершенные тесты: 1
01.05.2014, 19:24     Как сделать так, чтобы значения экземпляров класса не повторялись #10
Ну, наверное не совсем. Вообще, зависит от предпочтений разработчика. Смотрите, я постараюсь описать как я себе это представляю.
1. У Вас есть игровое поле - матрица. Каждая ячейка, занята или не занята плиткой.
2. У Вас есть плитка, которая имеет координату и значение.

По игре:
1. ...
2. Рандомим координаты, пока они не укажут на свободную ячейку. Создаем плитку по данным координатам.
3. Ловим движение, двигаем.
4. Обходим по всему полю, если есть плитка, смотрим ее соседей. Мержем в одну.
5. ...
6. Условие победы/проигрыша? Возврат к 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
//pseudo code
 
class Cell
{
     render()
     {
           GLDrawRect(x, y, w, h);
     }
 
     int x, y;
     int w, h;
}
 
class game_filed
{
    reder()
    {
        drawBorder();
 
        foreach(cell in cells)
        {
            if (cell) //Can be empty game position!
                 cel->render();
        }
    }
 
    cell* cels[SIZE][SIZE];
}
 
void global_render()
{
     //additionlal render
     game_filed->render();
 
     GLFlushBuffers();
}
Как-то так.
Yandex
Объявления
01.05.2014, 19:24     Как сделать так, чтобы значения экземпляров класса не повторялись
Ответ Создать тему
Опции темы

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