Форум программистов, компьютерный форум, киберфорум
Кроссплатфор­менная разработка
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/68: Рейтинг темы: голосов - 68, средняя оценка - 4.71
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562

Змейка

17.10.2010, 06:00. Показов 13028. Ответов 95
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
wxWidgets - вот и пошло первое написание игры. Ну относительно игры конечно. Проблема вот в чем. Нам препод показал как сделать, чтобы "змейка" двигалась. Поднастроил, чтобы она двигалась правильно. Влево - влево, вниз - вертикально вниз и т.п. Но есть проблемка. При таком коде, что соответственно:

C++
1
2
3
    m_coord +=
        wxGetKeyState(WXK_UP)? wxPoint(0, -10) : wxGetKeyState(WXK_DOWN) ? wxPoint(0, 10) : 
        wxGetKeyState(WXK_LEFT)? wxPoint(-10, 0) : wxGetKeyState(WXK_RIGHT)? wxPoint(10, 0) : wxPoint(10, 0);
Координата точки изменяется, только если держать кнопку. По дефолту идет вправо. Не коммильфо. Как запомнить последнюю нажатую кнопку и перемещать именно в ту сторону, какая кнопка была нажата?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.10.2010, 06:00
Ответы с готовыми решениями:

Змейка не работает
Неправильно работает хвост (add_hvost) . Что не так ? #include <iostream> #include <conio.h> #include <cstdlib> #include...

Змейка. Нужен совет как доработать программу
Недавно я зашел в тупик, работая над программой "Змейка". Но несмотря на то, что в общем и целом программа работает (змея двигается по...

Змейка на QT C++
Доброго времени суток! Начал изучение с++ QT и параллельно пробую писать игру змейка. Сама реализация игры почти готова - змейка...

95
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
20.10.2010, 23:41  [ТС]
Студворк — интернет-сервис помощи студентам
dxdy, На кьюте она легче пишется. Видел код полной игры. Непрофессиональный код конечно, довольно простой.
0
 Аватар для dxdy
99 / 99 / 14
Регистрация: 14.06.2010
Сообщений: 284
21.10.2010, 00:34
На кьюте она легче пишется.
можно подробнее по этому поводу.
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
21.10.2010, 01:25
Следовательно... включение

Такая некрасивая запись появляется из-за указателя.
C++
1
(*Sn)[i]
либо
C++
1
2
3
MySnake& snake = *Sn; 
...
snake[i]
P.S. То, что я говорил про наследование в предыдущем посте относится, естественно, к открытому наследованию.

Добавлено через 3 минуты
На кьюте она легче пишется.
Это только кажется. Никакой принципиальной разницы в данном случае между Qt и wxWidgets нет.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
21.10.2010, 07:48  [ТС]
rangerx, Кстати... А включение вообще нужно или же нет? Мб friend классом звено для змейки сделать?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
21.10.2010, 18:12
А включение вообще нужно или же нет? Мб friend классом звено для змейки сделать?
Честно говоря не вижу каким образом и для чего здесь можно задействовать friend класс. У тебя есть класс "змейка", "змейка" состоит из некоторого набора объектов класса "звено". У тебя роль этого набора выполняет вектор, как я понимаю. Что-то вроде
C++
1
2
3
4
5
6
7
8
typedef std::vector<MySection> Sections;
...
class MySnake
{
    private:
        Sections sections;
    ...
};
Всё. А само "звено" вообще ничего не должно знать о "змейке".
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
22.10.2010, 22:39  [ТС]
rangerx, Ну собственно да. Функции то есть нужные. Буду сегодня писать скорее всего.

Добавлено через 8 часов 46 минут
Итак... Вообще что-то не совсем получается.
Как должно происходить все - я примерно понял... НО...

Как отрисовать отдельный фрагмент? Впринципе отрисовывается... Но... Вообщем, правильный ли алгоритм? На числа не смотреть. Эксперементировал. const wxPoint& old_pt - значение координат до их изменений.
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
void MyCanvas::DoDraw(wxDC& dc, const wxPoint& pt, const wxPoint& old_pt)
{
    dc.SetBrush(wxBrush(wxColour("White")));
    static int cnt=0;
    size_t i=0;
    static wxPoint Coords;
    for(i=0; i<Sn->GetSnakeSize(); ++i)
    {
        //if(i==Sn->GetSnakeSize()-1)
        //{
        //  (*Sn)[i].SetSectCoord(pt+wxPoint((i-1)*10, 0));
        //}
        //else
        //{
        (*Sn)[i].SetSectCoord(old_pt+wxPoint(i+30, 0));
        //}
        if(cnt!=0&&i==Sn->GetSnakeSize()-1)
            (*Sn)[Sn->GetSnakeSize()-1].SetSectCoord(Coords);
        dc.DrawCircle((*Sn)[i].GetSectCoord(), 5);
    }
    dc.SetBrush(wxColour("GREE"));
    dc.DrawCircle((*Sn)[0].GetSectCoord(), 5);
    std::vector<MySection>::iterator Iter=Sn->GetSnake().begin();
    Sn->GetSnake().erase(Iter);
    Sn->GetSnake().resize(Sn->GetSnakeSize()+1);
    dc.SetBrush(wxColor("White"));
    (*Sn)[Sn->GetSnakeSize()-1].SetSectCoord(pt+wxPoint(i+15, 0));
    dc.DrawCircle((*Sn)[Sn->GetSnakeSize()-1].GetSectCoord(), 5);
    Coords=((*Sn)[Sn->GetSnakeSize()-1].GetSectCoord());
    cnt=1;
    std::ofstream ofs("Test.txt", std::ios::app);
    ofs<<pt.x<<' '<<pt.y<<' '<<old_pt.x<<' '<<old_pt.y<<'\n';
}
+ Как нормально завершить приложение в wxWidgets?
Пришлось использовать так.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool MyCanvas::IsAlive()
{
    const wxSize sz=GetClientRect().GetSize();
    if(((*Sn)[0].GetSectCoord().x>=sz.x||(*Sn)[0].GetSectCoord().y>=sz.y) ||
        (((*Sn)[0].GetSectCoord().x<0)||(*Sn)[0].GetSectCoord().y<0))
    {
        wxMessageBox(_T("Game over!\nYou lose!\n"), _T("\n"), wxOK | wxICON_ERROR, this);
        return false;
    }
//
 
И ловлю так:
    if (!IsAlive())
            exit(1);
Мессадж бокс начинает циклиться, даже если использовать exit(code);

Что я сделал за сегодня в итоге...

Разбил классы по хедерам.
Добавил некоторые новые функции. Но пока вопросы только те которые задал тут. В отрисовке - не могу понять, то-ли дело с числами, то-ли сам алгоритм неверен. Я так понимаю, что мы убираем элемент с хвоста -> закидываем элемент перед головой и так далее. Верно? По-моему код это и должен реализовать...

Добавлено через 19 часов 24 минуты
Кто подскажет как быть?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
23.10.2010, 00:54
Метод DoDraw должен только рисовать, а у тебя он занимается непонятно чем... Все движения и перестановки это поведение самой змейки, а не канвы. Кстати говоря, на мой взгляд возможно лучше не делать никаких DoDraw в классе MyCanvas, а сделать метод draw для классов MySection и MySnake. А их конструкторы пусть принимают указатель на канву на которой будут отрисовываться. MySection::draw() пусть рисует само звено, а MySnake::draw() пусть вызывает MySection::draw() для каждого из своих звеньев. Но делать так или оставить как есть решай сам.
+ Как нормально завершить приложение в wxWidgets?
Мессадж бокс начинает циклится, даже если использовать exit(code);
По тому, что ты привёл невозможно сказать почему он у тебя циклится. А закрыть окно в твоём случае можно так
C++
1
this->GetParent()->Close();
Хотя опять же, метод IsAlive я бы убрал вообще т.к. в обязанности канвы слежение за состоянием змейки не входит. Змейка сама должна сообщать может ли она двигаться дальше или нет. Я бы сделал это так, как писал несколькими постами выше, т.е.
C++
1
2
3
4
5
6
7
// змейка  врезалась в стену или столкнулась сама с собой
if( !snake->doMotion() )
{   
    timer->Stop();
    wxMessageBox(wxT("Game over!\nYou lose!\n"), wxT("\n"), wxOK | wxICON_ERROR, this);
    this->GetParent()->Close(); 
}
В отрисовке - не могу понять, то-ли дело с числами, то-ли сам алгоритм неверен. Я так понимаю, что мы убираем элемент с хвоста -> закидываем элемент перед головой и так далее. Верно? По-моему код это и должен реализовать...
То, что алгоритм верен по-моему очевидно ) Но брать непосредственно хвост и ставить его перед головой(циклический сдвиг) справедливо только если бы ты использовал список. Т.е. в списке при этом не создавался бы новый элемент, а менялись бы значения указателей. Если же ты используешь вектор, то в перебросе последнего элемента перед головой смысла вообще никакого нет. Просто удали последний элемент и создай перед головой новый(c установкой для него соответствующей позиции естественно). deque, ещё раз повторю, в сравнении с вектором использовать было бы намного лучше.
Как отрисовать отдельный фрагмент?
Что ты имеешь в виду?
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
23.10.2010, 00:54  [ТС]
rangerx, DoDraw то вцелом только и рисует... Про методы классов да, пожалуй получше будет.

Но я собственно убираю последний элемент и ресайзаю вектор, после чего рисую с новыми координатами элемент перед головой. Один раз это проходит. Далее змейка так и остается. Т.е.

Было.

Code
1
о о о о
Нажали вниз

Code
1
2
 о о о
     о
Больше ничего не нажимали, состояние запомнено, коорды меняются


Code
1
2
 о о о
     о
+ я несколько не понимаю какие устанавливать координаты. Ну не от балды же их ставить... Точка pt, и old_pt вполне нормально работает. Но если не прибавлять к ним что-либо секции будут рисоваться друг на друге... Что не есть хорошо. Совсем.
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
23.10.2010, 01:21
DoDraw то вцелом только и рисует...
C++
1
2
3
std::vector<MySection>::iterator Iter=Sn->GetSnake().begin();
Sn->GetSnake().erase(Iter);
Sn->GetSnake().resize(Sn->GetSnakeSize()+1);
Это называется "только и рисует"? ))
Но я собственно убираю последний элемент и ресайзаю вектор, после чего рисую с новыми координатами элемент перед головой.
Пробуй так
sections.insert(sections.begin(), sections.front());
sections.pop_back();
После это делай шаг (doMotion или что там у тебя).
+ я несколько не понимаю какие устанавливать координаты. Ну не от балды же их ставить... Точка pt, и old_pt вполне нормально работает. Но если не прибавлять к ним что-либо секции будут рисоваться друг на друге... Что не есть хорошо. Совсем.
Ты не понимаешь как сделать движение или задать начальные координаты при создании змейки? Или что?
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
23.10.2010, 01:25  [ТС]
rangerx, Движение то делается. Но вот это
C++
1
        (*Sn)[i].SetSectCoord(old_pt+wxPoint(i*10, 0));
От балды ведь ставим получается...

А разве шаг сам не делается? Мы ведь из таймера вызываем, в котором по сути делается шаг итак...

C++
1
2
sections..insert(listOfLinks.begin(), listOfLinks.front());
sections.pop_back();
Это я так понимаю, вместо удаления элемента через итератор?

Никогда бы не подумал, что так дико буду тупить над реализацией змейки...
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
23.10.2010, 02:35
Это я так понимаю, вместо удаления элемента через итератор?
Да. Только вместо listOfLinks должно быть sections... Это просто я неудачно отредактировал сообщение )
А разве шаг сам не делается? Мы ведь из таймера вызываем, в котором по сути делается шаг итак...
Я имел в виду, что этот код должен выполнится ещё до того, как будет сделан шаг. Т.е. сначала перегруппировка змейки, а потом шаг. При шаге у змейки меняется только позиция новой головы(координаты которай после
C++
1
sections.insert(sections.begin(), sections.front());
совпадают с координатами старой) и больше ничего.
Движение то делается. Но вот это
От балды ведь ставим получается...
Давай лучше ты выложишь весь свой проект, и я посмотрю что там у тебя и как, а то так долго ещё можно выяснять что к чему...
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
23.10.2010, 02:44  [ТС]
rangerx, Не против если не в архиве? По файлам покидаю.

Вся проблема в том, что я запутался в коде + с настолько новой областью довольно трудно разобраться...

Спасибо тебе за помощь! Сейчас смысла сидеть всю ночь видимо нет, потому завтра у препода спрошу, чтобы он посмотрел код... Посоветует что-нибудь наверняка.

Как посмотришь код - отпишись, что не так, что должно быть по другому. Хорошо?

Код
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
//Food.h
#include "wx/wx.h"
 
class MyFood
{
public:
    MyFood(MyCanvas* Canv)
    {
    }
 
    ~MyFood()
    {
    }
 
    void SetFoodCoord(const wxPoint& s)
    {
        food_coord.x=s.x;
        food_coord.y=s.y;
    }
 
    const wxPoint GetFoodCoord() const
    {
        return food_coord;
    }
 
private:
    wxPoint food_coord;
};
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
//Snake.h
#include "wx/wx.h"
 
#include <deque>
 
class MyCanvas;
 
class MySection
{
public:
    MySection(MyCanvas* Canv)
    {
        sect_coord.x=0;
        sect_coord.y=0;
    }
 
    ~MySection()
    {
    }
    
    const wxPoint GetSectCoord() const
    {
        return sect_coord;
    }
 
    void SetSectCoord(const wxPoint& s)
    {
        sect_coord.x=s.x;
        sect_coord.y=s.y;
    }
 
    void Draw(wxDC& dc, const wxPoint& coord, const wxPoint& old_c);
 
protected:
    wxPoint sect_coord;
};
 
class MySnake
{
public:
    MySnake(MyCanvas* Canv)
    {
    }
 
    ~MySnake()
    {
    }
 
    std::deque<MySection>& GetSnake()
    {
        return Snake;
    }
 
    const size_t GetSnakeSize() const
    {
        return Snake.size();
    }
 
    MySection& operator [](int i)
    {
        return Snake[i];
    }
    
    void Draw(wxDC& dc, const wxPoint& coord, const wxPoint& old_c);
    
    void Redraw(wxDC& dc, const wxPoint& coord, const wxPoint& old_c);
private:
    std::deque<MySection> Snake;
};
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
//Snake.cpp
#include <wx/wx.h>
 
#include "Snake.h"
 
void MySection::Draw(wxDC& dc, const wxPoint& coord, const wxPoint& old_c)
{
    dc.DrawCircle(coord, 5);
}
 
void MySnake::Draw(wxDC& dc, const wxPoint& coord, const wxPoint& old_c)
{
    dc.SetBrush(wxColour("White"));
    for(size_t i=0; i<Snake.size(); ++i)
    {
        Snake[i].Draw(dc, old_c+wxPoint(i*10, 0), coord);
    }
    Redraw(dc, coord, old_c);
}
 
void MySnake::Redraw(wxDC& dc, const wxPoint& coord, const wxPoint& old_c)
{
    dc.SetBrush(wxColour("Gree"));
    Snake.begin()->Draw(dc, old_c, coord);
    Snake.insert(Snake.end(), Snake.front());
    Snake.pop_front();
    //Snake.erase(Snake.begin());
    //Snake.resize(Snake.size()+1);
    dc.SetBrush(wxColour("White"));
    Snake[Snake.size()-1].Draw(dc, coord+wxSize(30, 0), old_c);
}
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//minimal.cpp
class MyFrame : public wxFrame
{
public:
    // ctor(s)
    MyFrame(const wxString& title);
 
    // event handlers (these functions should _not_ be virtual)
    void OnQuit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
private:
    // any class wishing to process wxWidgets events must use this macro
    DECLARE_EVENT_TABLE()
};
 
class MyCanvas : public wxScrolledWindow
{
public:
    MyCanvas(MyFrame* POb):
      wxScrolledWindow(POb, wxID_ANY, wxDefaultPosition,
        wxSize(640, 480)),Sn(new MySnake(this)), Food(new MyFood(this))
    {
        m_timer.SetOwner(this);
        m_timer.Start(1000);
        Sn->GetSnake().resize(4, this);
    }
      ~MyCanvas()
      {
          delete Sn;
      }
protected:
    void OnTimer(wxTimerEvent& event);
    void OnPaint(wxPaintEvent& event);
    void OnKeyboard(wxKeyEvent& event);
    void Invalidate()
    {
        Refresh();
    }
 
    wxTimer m_timer;
    wxPoint m_coord;
    wxTimer food_timer;
    wxPoint old_m_coord;
 
private:
    enum Direction {UP, DOWN, RIGHT, LEFT} currDirection;
    void DoDraw(wxDC& dc, const wxPoint& pt, const wxPoint& old_pt);
    void DoMotion(const Direction& curr);
    void DrawFood(wxDC& dc);
    bool IsNotExist();
    bool IsAlive();
    //void RedrawSect(wxDC& dc, const wxPoint& pt);
 
    MySnake* Sn;
    MyFood* Food;
 
    DECLARE_EVENT_TABLE()
};
 
enum
{
    Minimal_Quit = wxID_EXIT,
 
    Minimal_About = wxID_ABOUT,
 
    Minimal_Hello = 1
};
 
 
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(Minimal_Quit,  MyFrame::OnQuit)
    EVT_MENU(Minimal_About, MyFrame::OnAbout)
END_EVENT_TABLE()
 
BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
    EVT_PAINT(MyCanvas::OnPaint)
    EVT_TIMER(wxID_ANY, MyCanvas::OnTimer)
    EVT_KEY_DOWN(MyCanvas::OnKeyboard)
END_EVENT_TABLE()
 
IMPLEMENT_APP(MyApp)
 
bool MyApp::OnInit()
{
    if ( !wxApp::OnInit() )
        return false;
 
    // create the main application window
    MyFrame *frame = new MyFrame(_T("Draw line App"));
    frame->Show(true);
    return true;
}
 
MyFrame::MyFrame(const wxString& title)
       : wxFrame(NULL, wxID_ANY, title)
{
    SetIcon(wxICON(sample));
 
#if wxUSE_MENUS
    wxMenu *fileMenu = new wxMenu;
 
    wxMenu *helpMenu = new wxMenu;
 
    helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
 
    fileMenu->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
 
    wxMenuBar *menuBar = new wxMenuBar();
    menuBar->Append(fileMenu, _T("&File"));
    menuBar->Append(helpMenu, _T("&Help"));
 
    SetMenuBar(menuBar);
#endif 
 
#if wxUSE_STATUSBAR
    CreateStatusBar(2);
    SetStatusText(_T("Welcome to wxWidgets!"));
#endif 
    MyCanvas* Ob= new MyCanvas(this);
}
 
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    Close(true);
}
 
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxMessageBox(wxString::Format(
                    _T("Welcome to %s!\n")
                    _T("\n")
                    _T("This is the minimal wxWidgets sample\n")
                    _T("running under %s."),
                    wxVERSION_STRING,
                    wxGetOsDescription().c_str()
                 ),
                 _T("About wxWidgets minimal sample"),
                 wxOK | wxICON_INFORMATION,
                 this);
}
 
//void MyCanvas::DoDraw(wxDC& dc, const wxPoint& pt, const wxPoint& old_pt)
//{
//    dc.SetBrush(wxBrush(wxColour("White")));
//  static int cnt=0;
//  size_t i=0;
//  static wxPoint Coords;
//  for(i=0; i<Sn->GetSnakeSize(); ++i)
//  {
//      (*Sn)[i].SetSectCoord(old_pt+wxPoint(i*10, 0));
//      //if(cnt!=0&&i==Sn->GetSnakeSize()-1)
//      //  (*Sn)[Sn->GetSnakeSize()-1].SetSectCoord(Coords);
//      dc.DrawCircle((*Sn)[i].GetSectCoord(), 5);
//  }
//  dc.SetBrush(wxColour("GREE"));
//  dc.DrawCircle((*Sn)[0].GetSectCoord(), 5);
//  
//  //Sn->GetSnake().insert(Sn->GetSnake().begin(), Sn->GetSnake().front());
//  //Sn->GetSnake().pop_back();
//  DoMotion(currDirection);
//  Sn->GetSnake().erase(Sn->GetSnake().begin());
//  Sn->GetSnake().resize(Sn->GetSnakeSize()+1, MySection(this));
//  dc.SetBrush(wxColour("White"));
//  (*Sn)[Sn->GetSnakeSize()-1].SetSectCoord(pt+wxPoint(i*10, 0));
//  dc.DrawCircle((*Sn)[Sn->GetSnakeSize()-1].GetSectCoord(), 5);
//  //Coords=((*Sn)[Sn->GetSnakeSize()-1].GetSectCoord());
//  //cnt=1;
//}
 
void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
{
    wxPaintDC dc(this);
    //DoDraw(dc, wxPoint(20, 20), wxPoint(20, 20));
}
 
void MyCanvas::OnTimer(wxTimerEvent& WXUNUSED(event))
{
    DoMotion(currDirection);
    wxMemoryDC dc;
    wxSize CS = GetClientRect().GetSize();
    dc.SelectObject(wxBitmap(CS.GetHeight(), CS.GetWidth()));
    //DoDraw(dc, m_coord, old_m_coord);
    Sn->Draw(dc, m_coord, old_m_coord);
    wxClientDC clientDC(this);
    clientDC.Blit(wxPoint(0, 0), CS, &dc, wxPoint(0, 0));
}
 
void MyCanvas::DoMotion(const Direction& curr)
{
    old_m_coord=m_coord;
    m_coord+=
        curr==UP ? wxPoint(0, -15) : curr==DOWN ? wxPoint(0, 15) :
        curr==LEFT ? wxPoint(-15, 0) : curr==RIGHT ? wxPoint(15, 0) : wxPoint(0, 0);
    //if (!IsAlive())
    //      exit(0);
}
 
void MyCanvas::OnKeyboard(wxKeyEvent& WXUNUSED(event))
{
    wxGetKeyState(WXK_UP) ? currDirection=UP :
        wxGetKeyState(WXK_DOWN) ? currDirection=DOWN :
        wxGetKeyState(WXK_RIGHT) ? currDirection=RIGHT :
        wxGetKeyState(WXK_LEFT) ? currDirection=LEFT :
        0;
}
 
void MyCanvas::DrawFood(wxDC& dc)
{
    const wxSize sz=GetClientRect().GetSize();
    dc.SetBrush(wxBrush(wxColour("Green")));
    Food->SetFoodCoord(wxPoint(rand()%sz.x, rand()%sz.y));
    dc.DrawCircle(Food->GetFoodCoord(), 15);
}
 
bool MyCanvas::IsNotExist()
{
    for(size_t i=0; i<Sn->GetSnakeSize(); ++i)
    {
        if(((*Sn)[i].GetSectCoord().x==(*Food).GetFoodCoord().x) &&
            ((*Sn)[i].GetSectCoord().y==(*Food).GetFoodCoord().y))
        {
            return false;
        }
    }
    return true;
}
 
bool MyCanvas::IsAlive()
{
    const wxSize sz=GetClientRect().GetSize();
    if(((*Sn)[0].GetSectCoord().x>=sz.x||(*Sn)[0].GetSectCoord().y>=sz.y) ||
        (((*Sn)[0].GetSectCoord().x<0)||(*Sn)[0].GetSectCoord().y<0))
    {
        wxMessageBox(_T("Game over!\nYou lose!\n"), _T("\n"), wxOK | wxICON_ERROR, this);
        return false;
    }
    return true;
}
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
23.10.2010, 03:49
Для начала тебе просто нужно сесть и подумать над поведением объектов. Т.е. продумать сам интерфейс классов. Например змейка
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Snake
{
    private:
        Sections sections_;       // собственно сами секции/звенья
        Direction currDirection_; // текущее направление движения
        Canvas* canvas_;          // канва
    public:
        // собственно конструктор
        Snake(Canvas* canvas, const wxPoint& startPosition, size_t sectionsCount = 3);
 
        // установить новое направление движения
        setDirection(Direction newDirection); 
 
        // сделать шаг
        bool doMotion();
 
        // присоединить новое звено
        void append();
 
        // отрисовать змейку на канве
        void draw();
};
И так всё остальное. Т.е. когда будешь видеть перед собой интерфейс будет проще думать над реализацией )) А так, смотри, что тебе скажет препод.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
23.10.2010, 04:10  [ТС]
rangerx, Спасибо! Код я так понимаю лучше с нуля набить?
ЗЫ Код совсем плох?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
23.10.2010, 04:25
Код я так понимаю лучше с нуля набить?
ЗЫ Код совсем плох?
Если ты уже успел запутаться в собственном коде хотя его не так уж и много, то естественно надо что-то менять. ) Подойди к преподу, покажи свой код, послушай, что он скажет, а там уже решишь набивать с нуля или нет )
P.S. К тому, что я написал ещё не мешало бы добавить метод для получения позиции головы змейки чтобы иметь возможность сравнить позицию головы с позицией того, что собственно змейка будет собирать. Что-то вроде
C++
1
const wxPoint& headPosition() const;
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
24.10.2010, 17:10  [ТС]
rangerx, Препод говорил многое... Но уже ничего не помню, помню, что мне точно надо будет все переписать, ибо я переборщил несколько... Так что собственно вот...
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
24.10.2010, 20:11
ибо я переборщил несколько...
В чём именно?
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
24.10.2010, 20:32  [ТС]
rangerx, Блин. Сегодня боюсь не вспомню.
Вообщем буду пробовать переписывать. Начиная с завтра-послезавтра. К субботе надо постараться сделать...)
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
26.10.2010, 02:58  [ТС]
Чорт. Видимо я совершенно не способен к пониманию графики...

Сделал что-то вроде такого... Интерфейс по сути неплохой...

Я решил не отрывать голову/хвост у змеи, а просто менять координаты в соотвествии с нужным направлением.
Т.е. движение допустим вправо изначально. Нажали вниз, голова сдвинулась вниз, остальные элементы дальше вправо. И т.д. Это ведь должно быть возможно? Не могу только понять как это связать с событием:

C++
1
2
3
4
5
6
7
8
void MyCanvas::OnKeyboard(wxKeyEvent& WXUNUSED(event))
{
    wxGetKeyState(WXK_UP) ? currDir=UP :
        wxGetKeyState(WXK_DOWN) ? currDir=DOWN :
        wxGetKeyState(WXK_RIGHT) ? currDir=RIGHT :
        wxGetKeyState(WXK_LEFT) ? currDir=LEFT :
        0;
}
Я в правильную сторону мыслю или нет?

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
class MyCanvas;
 
enum Direction
{
    UP,
    RIGHT, 
    LEFT,
    DOWN,
    NONE
};
 
class MySection
{
public:
    MySection():sect_coord(wxPoint(0, 0))
    {
    }
 
    const wxPoint GetCoord() const
    {
        return sect_coord;
    }
 
    void SetCoord(const wxPoint& c)
    {
        sect_coord.x=c.x;
        sect_coord.y=c.y;
    }
 
    void DoMotion()
    {
        sect_coord+=
            currDir==UP ? wxPoint(0, -15) : currDir==DOWN ? wxPoint(0, 15) :
            currDir==LEFT ? wxPoint(-15, 0) : currDir==RIGHT ? wxPoint(15, 0) : wxPoint(0, 0);
    }
 
    void Draw (wxDC& dc, const size_t rad=5)
    {
        dc.DrawCircle(sect_coord, rad);
    }
private:
    wxPoint sect_coord;
    Direction currDir;
};
 
class MySnake
{
public:
    MySnake(MyCanvas* c, size_t sect_count=3)
    {
        canv=c;
        Sections.resize(sect_count);
    }
 
    void DoMotion()
    {
        for(size_t i=0; i<Sections.size(); ++i)
            Sections[i].DoMotion();
    }
    
    void Draw(wxDC& dc)
    {
        dc.SetBrush(wxColour("White"));
        for(size_t i=0; i<Sections.size(); ++i)
        {
            Sections[i].SetCoord(Sections[i].GetCoord()+wxPoint(10*i, 0));
            Sections[i].Draw(dc);
        }
    }
 
    void SetDir(const Direction& New)
    {
        currSnakeDir=New;
    }
private:
    std::vector<MySection> Sections;
    MyCanvas* canv;
    Direction currSnakeDir;
};
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
26.10.2010, 04:53
Я решил не отрывать голову/хвост у змеи, а просто менять координаты в соотвествии с нужным направлением. Т.е. движение допустим вправо изначально. Нажали вниз, голова сдвинулась вниз, остальные элементы дальше вправо.
Так визуально оно так и будет выглядеть при перемещении хвоста вперёд... Смотри
@@@ - движемся влево (зелёный это хвост)
Тепер нажимаем кнопку "вниз"(происходит два шага): 1)
@@ - хвост стал точно на место головы(т.е. по порядку перемещённый элемент стал пeрвым(перед головой), но его координаты пока совпадают с координатами старой головы) Внизу под зелёным старая голова. )
2) Тепер перемещаем новую голову(зелёную) вниз, и получаем
@@
@
и т.д. Ты же, как я понимаю, хочешь сделать сдвиг всех элементов вектора... Сделать это конечно возможно, но только зачем, непонятно. Это самое неэффективное решение(если ещё учесть, что ты используешь вектор), которое только можно придумать.
По поводу функции OnKeyboard... Во-первых зачем все эти wxGetKeyState? Во-вторых, почему направление у тебя опять "гуляет" отдельно от змейки(или это просто старый вариант функции)? И наконец зачем так извращаться с тернарным оператором, когда можно использовать switch?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void MyCanvas::OnKeyboard(wxKeyEvent& event)
{
    switch(event.m_keyCode)
    {
        case WXK_LEFT :
            snake->setDirection(LEFT);
        break;
 
        case WXK_RIGHT :
            snake->setDirection(RIGHT);
        break;
       ...
    }
}
Я в правильную сторону мыслю или нет?
В принципе в правильную(на первый взгляд), за исключением метода DoMotion в MySection. Вот этот метод надо бы перенести в MySnake(вместо того что сейчас там есть) и таким образом менять положение головы, как я написал выше. Т.е.
C++
1
2
3
4
5
6
7
8
9
10
11
void MySnake::DoMotion()
{
     // здесь перемещение хвоста на место головы
      ...
   
     // а теперь шаг, который делает новая голова
     //(только следующий код естественно переписать так, чтобы менялась позиция головы)
     sect_coord+=
         currDir==UP ? wxPoint(0, -15) : currDir==DOWN ? wxPoint(0, 15) :
         currDir==LEFT ? wxPoint(-15, 0) : currDir==RIGHT ? wxPoint(15, 0) : wxPoint(0, 0);
 }
И магические числа(15) тоже не мешало бы убрать. И еще, конструктору MySection не мешало бы сделать параметры: позиция(начальная) и радиус(а не делать это каждый раз в методе Draw). Пока как-то так. )
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.10.2010, 04:53
Помогаю со студенческими работами здесь

Ошибка undefined reference to в игре "Змейка"
В главном файле такие ошибки: #include &lt;QApplication&gt; #include &quot;Game.h&quot; Game* game; int main(int argc, char *argv) { ...

Прокомментировать код игры "змейка" в QT
Помогите прокомментировать код игры (подписать как, что и для чего).

Ошибки в игре "Змейка"
Не получается исправить ошибки в коде :(

Игра "Змейка": чтобы змейка не съедала сама себя
Здравствуйте! Пишу змейку на VB 2010. Не получается составить условие того, что бы змейка не ползла в направлении обратному...

Змейка
Написал только движение квадрата влево,вправо,вверх,вниз ,но не могу им управлять он движется до конца поля ,а только потом можно...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru