Форум программистов, компьютерный форум, киберфорум
Программирование игр
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/29: Рейтинг темы: голосов - 29, средняя оценка - 4.86
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66

Прошу критики игры "Змейка"

20.06.2018, 15:06. Показов 6430. Ответов 85
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет.
Недавно написал змейку.
Прошу оценить и покритиковать немного,мб какие-то предложения,поправки.
Вложения
Тип файла: rar Project.rar (12.87 Мб, 47 просмотров)
Тип файла: rar отдельно main.rar (1.3 Кб, 11 просмотров)
Тип файла: rar отдельно екзешник.rar (24.7 Кб, 25 просмотров)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.06.2018, 15:06
Ответы с готовыми решениями:

Змейка, завершение игры
Нужно сделать чтобы змейка ела 5 яблок и игра заканчивалась, но не могу понять как это сделать( Вот сам код #include...

Прошу критики
Всем привет! Прошу старших коллег оценить код ниже. Любая критика приветствуется. Стоит задача спарсить страницы с объявлениями о...

Прошу вашей критики
Начинаю делать собственный проект www.geo-rus.ru. Жду вашей критики по всем фронтам. :) Главный вопрос: стоит ли он развития, или...

85
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
15.07.2018, 09:01
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от anton3d Посмотреть сообщение
int lastposx[100], lastposy[100];
Заверните все-таки в структуру:
C
1
2
3
4
5
6
7
8
9
10
struct Point{
  int x, y;
};
struct Snake {
  Point hpos;
  Point lastpos[100];
  int len;
  int dir, ldir, sdir; //что это?
  char head, tail; //а это? Символ, используемый для головы? А зачем?
};
C
1
2
3
4
struct HelpVars {//на первый взгляд не лучшее название
    char rkey;
    int coutr, ans;
};
Цитата Сообщение от anton3d Посмотреть сообщение
m.mposx = rand() % (fldwidth - 4) + 2;//возле стенок очень просто подохнуть,поэтому костылем отнимаем 4ед(2 от правой стены/2 от левой(т.е.одна на символ стены,а вторая на пустой после стены-таким образом еда спавнится максимум за один символ от стены и меня никто не будет ругать за кривую механику поворота(заметка-попытатся починить потом)))
Вот этот комментарий стоило разделить на два. Сначала перед рандомами оправдаться почему не вплотную к стенам, потом отдельно чтобы не попадало внутрь тела.
Ну и для рандома в заданных пределах стоит написать отдельную функцию.
Цитата Сообщение от anton3d Посмотреть сообщение
//изза кривизны кода пропадает один уголок-этот костыль все чинит

//стены вертикальные
//стены вертикальные
//стены горизонтальные
//стены горизонтальные
Отрисовку фона лучше вынести в отдельную процедуру. Во-первых, в том же OpenGL/DX в любом случае приходится перерисовывать ВСЮ сцену на каждом кадре. Во-вторых, если вдруг захочется в середине игры поменять заполнение.
Цитата Сообщение от anton3d Посмотреть сообщение
если все гуд,приступаю к curses
Да давно пора. Никто ж не запрещает одновременно менять фундамент и раскрашивать стены неприличными надписями строящегося здания.
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
15.07.2018, 18:49  [ТС]
COKPOWEHEU,
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Заверните все-таки в структуру:
так
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
int lastposx[100], lastposy[100];
в структуре Snake,или суть в том,чтобы сделать вложенную структуру?
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
dir, ldir, sdir; //что это?
текущее направление,прошлое направление(нужно сохранять прошлое,чтобы заблокировать движение в противоположную от текущего направления сторону) и вспомогательная переменная-использую при переводе с чара в инт(s.sdir = static_cast<int>(hv.rkey);//переводим)
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
//на первый взгляд не лучшее название
Хмм,вроде правильно перевел-просто ничего лучше чем "вспомогательные переменные" не придумал
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Ну и для рандома в заданных пределах стоит написать отдельную функцию.
так я же выделил отдельную функцию для спавна еды-просто нужно проверять чтобы она не спавнилась внутри змеи,разбивать 3 строчки кода на две функции-кажется мне не лучшим решением.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Отрисовку фона лучше вынести в отдельную процедуру. Во-первых, в том же OpenGL/DX в любом случае приходится перерисовывать ВСЮ сцену на каждом кадре. Во-вторых, если вдруг захочется в середине игры поменять заполнение.
Хмм,да думаю это стоит сделать,но отделю от инициализации отдельно кусок с инициализацией поля,сделаю одну функцию вместе со стенами и углами.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
head, tail; //а это? Символ, используемый для головы? А зачем?
Я думал что буду использовать эти символы чаще одного раза за весь код.Вроде как красиво,но пока что бесполезно,оставлю пока,вдруг еще понадобится(была мысль сделать две змейки на одном поле,есть в голове реализация управления с локального компьютера,думаю еще попробую прикрутить сеть,если дело дойдет)

Добавлено через 17 минут
COKPOWEHEU, c curses морока получается,вот подробнее тут:https://code-live.ru/post/installing-pdcurses/
Так вот почему я так долго возился(
0
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
16.07.2018, 00:10
Цитата Сообщение от anton3d Посмотреть сообщение
в структуре Snake,или суть в том,чтобы сделать вложенную структуру?
я же привел пример. Специальная служебная структура для двумерной точки. И этой структурой описывать все точки змеи, или еды, или чего-то еще. Структура вполне может быть полем другой структуры, это не запрещено.
Цитата Сообщение от anton3d Посмотреть сообщение
так я же выделил отдельную функцию для спавна еды-просто нужно проверять чтобы она не спавнилась внутри змеи,разбивать 3 строчки кода на две функции-кажется мне не лучшим решением.
Тут немного другое соображение. Рандом в диапазоне нужен довольно часто, поэтому эту строчку можно вынести в функцию, а потом таскать из проекта в проект. Если боитесь за производительность, ее можно объявить как inline (хотя компиляторы нынче умные, что надо сами инлайнят).
Цитата Сообщение от anton3d Посмотреть сообщение
c curses морока получается
Честно, не пробовал. Основная система у меня Linux, а перезагружаться или запускать виртуалку только чтобы проверить как программировать в других системах пока что нет желания.
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
16.07.2018, 13:35  [ТС]
покрутил mingw-нашел там поддержку curses-хмм
попробую скомпилировать заголовочные файлы для visual studio,если не получится буду компилировать через mingw,а что еще делать то

Добавлено через 1 час 43 минуты
перепробовал все что мог и vs и devcpp
Все нормально работает только через консольную компиляцию mingw,код буду править в notepad++,ну лучше уж так чем никак)

Добавлено через 8 минут
по непредвиденным обстоятельствам меня не будет до конца месяца,бай
0
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
16.07.2018, 13:36
Неужели в том же devcpp нельзя вручную задать флаги компилятора?
0
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
16.07.2018, 14:03
Только что проверил. Не без танца с бубном, но работает нормально.
На всякий случай выкладываю свои библиотеки.
Теперь о танцах:
1. Распаковываем библиотеки в какую-нибудь папку. У меня это было C:/Users/user/Downloads/ncurses_mingw32.
2. В свойствах проекта (ctrl+H) выбираем 32-битную систему (потому что мои библиотеки 32-битные. Если найдете 64-битные - используйте их).
3. На вкладке Параметры (Parameters) добавляем к проекту библиотеку (Add library or object) libncursesw.a - можно с полным путем, можно нет, в любом случае пути еще будем настраивать
4. На вкладке Директории (Directories) в подвкладке Library directories задаем путь к либам (*.lib). В моем случае это C:/Users/user/Downloads/ncurses_mingw32/lib
5. Там же, в подвкладке Include directories добавляем пути к заголовкам (*.h). В моем случае это
C:/Users/user/Downloads/ncurses_mingw32/include
C:/Users/user/Downloads/ncurses_mingw32/include/ncursesw
Вроде все
Проверял на виртуалке с win7
Вложения
Тип файла: rar ncurses_mingw32.rar (613.1 Кб, 3 просмотров)
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
03.08.2018, 20:19  [ТС]
COKPOWEHEU,Хай,у меня тут проблемка с этим проклятием
Я сначала хотел править старый код,но до меня быстро дошло-что проще будет заново все сделать,и я пока набросал черновик.
Вот есть код:
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
#include <curses.h>
 
bool game_status = true;
char field[24][80],head;
int head_pos_x,head_pos_y,score,key;
 
void init(){
    for (int i = 0; i < 24; ++i){for (int j = 0; j < 80; ++j)field[i][j]=' ';}
    for (int i = 0; i < 24; ++i)field[i][0] = '#';
    for (int i = 0; i < 24; ++i)field[i][79] = '#';
    for (int i = 1; i < 80; ++i)field[0][i] = '#';
    for (int i = 1; i < 80; ++i)field[23][i] = '#';
    score = 0;
    head = '@';
    head_pos_x = 15;
    head_pos_y = 11;
}
 
void draw(){
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j)addch(field[i][j]);
    }
    printw("SCORE: %i", score);
    refresh();
    erase();//чистит экран(без refresh не работает)
}
 
void update(){
    field[head_pos_y][head_pos_x]=head;
    ++score;
}
 
int main(){
    initscr();
    curs_set(0);
    init();
    while(game_status){
        draw();
        update();
    }
    endwin();
    return 0;
}
как можно видеть,он не стирает весь экран,а только то,что изменилось(т.е. переменную score)
меня это очень обрадовало и я подумал что если все правильно сделать-то игра не будет мигать.
тут я дошел до момента,где хочу обрабатывать вводимые клавиши.
постарался реализовать кусочек Вашего кода(добавил таймаут,цбрейк и тут началась лажа- появилось мигание,еще и какое -то корявое):
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
#include <curses.h>
 
bool game_status = true;
char field[24][80],head;
int head_pos_x,head_pos_y,score,key;
 
void init(){
    for (int i = 0; i < 24; ++i){for (int j = 0; j < 80; ++j)field[i][j]=' ';}
    for (int i = 0; i < 24; ++i)field[i][0] = '#';
    for (int i = 0; i < 24; ++i)field[i][79] = '#';
    for (int i = 1; i < 80; ++i)field[0][i] = '#';
    for (int i = 1; i < 80; ++i)field[23][i] = '#';
    score = 0;
    head = '@';
    head_pos_x = 15;
    head_pos_y = 11;
}
 
void draw(){
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j)addch(field[i][j]);
    }
    printw("SCORE: %i", score);
    refresh();
    erase();//чистит экран(без refresh не работает)
}
 
void update(){
    field[head_pos_y][head_pos_x]=head;
    ++score;
    key = getch();
}
 
int main(){
    initscr();
    curs_set(0);
    timeout(5);
    cbreak();
    init();
    while(game_status){
        draw();
        update();
    }
    endwin();
    return 0;
}
Тут я понял что нужен kbhit,ну просто пипец как нужен.А его в curses нет((Подключил конио-они конфликтуют и не пашут.
Я где-то затупил?Что Вы можете посоветовать?

Вот еще пример того,что оно перерисовывает только участки которые изменились:
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
#include <curses.h>
 
bool game_status = true;
char field[24][80],head;
int head_pos_x,head_pos_y,score,key;
 
void init(){
    for (int i = 0; i < 24; ++i){for (int j = 0; j < 80; ++j)field[i][j]=' ';}
    for (int i = 0; i < 24; ++i)field[i][0] = '#';
    for (int i = 0; i < 24; ++i)field[i][79] = '#';
    for (int i = 1; i < 80; ++i)field[0][i] = '#';
    for (int i = 1; i < 80; ++i)field[23][i] = '#';
    score = 0;
    head = '@';
    head_pos_x = 15;
    head_pos_y = 11;
}
 
void draw(){
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j)addch(field[i][j]);
    }
    printw("SCORE: %i", score);
    refresh();
    erase();//чистит экран(без refresh не работает)
}
 
void update(){
    field[head_pos_y][head_pos_x]=head;
    ++head_pos_x;
    ++score;
}
 
int main(){
    initscr();
    curs_set(0);
    init();
    while(game_status){
        draw();
        update();
    }
    endwin();
    return 0;
}
Очень хочется реализовать все красиво.
Но мне начинает казаться что это все бесполезная трата времени,особенно если не получится избавится от мигания.
(Кстати до меня еще дошло,что я структуры мега тупо использовал в старом коде-можно намного эффективнее)
0
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
04.08.2018, 08:50
Цитата Сообщение от anton3d Посмотреть сообщение
COKPOWEHEU,Хай,у меня тут проблемка с этим проклятием
Что вам стоило вспомнить об этом вчера утром, когда я был на работе с настроенным окружением?..
Цитата Сообщение от anton3d Посмотреть сообщение
C
1
2
3
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j)addch(field[i][j]);
    }
А если ширина окна больше 80 символов? Съедет ведь. Добавьте в конце каждой строки вывод символов "\n\r"
Цитата Сообщение от anton3d Посмотреть сообщение
Тут я понял что нужен kbhit,ну просто пипец как нужен.
Ни в коем случае! Достаточно getch().
Исправил ваш код:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(){
    initscr();
    
    //не забываем настроить режим работы
    noecho();
    curs_set(0);
    start_color();
    timeout(100);
    set_escdelay(0);
    keypad(stdscr, TRUE);
    mousemask(ALL_MOUSE_EVENTS, NULL);
    cbreak();
    leaveok(stdscr,false);
    nonl();
...
C
1
2
3
4
5
6
void update(){
    field[head_pos_y][head_pos_x]=head;
    ++score;
    char key = getch(); //ввод символа
    if(key == 27)game_status=0;
}
C
1
2
3
4
5
6
7
8
void draw(){
    move(0,0); //чтобы начать отрисовку с угла
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j)addch(field[i][j]);
        addch('\n'); addch('\r'); //перевод строки
    }
    printw("SCORE: %i", score);
}
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
04.08.2018, 10:40  [ТС]
COKPOWEHEU,
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Что вам стоило вспомнить об этом вчера утром, когда я был на работе с настроенным окружением?..
Хех)Вчера утром я хотел сам разобраться,но что-то пошло не так.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А если ширина окна больше 80 символов? Съедет ведь. Добавьте в конце каждой строки вывод символов "\n\r"
при добавлении \n получается какая-то лажа,лично на моем терминале это выглядит так(прикреплю скрины внизу)
Хотел еще управлять размерами окна,или даже создать со своими параметрами(но у меня не получилось((()
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
//не забываем настроить режим работы
* * noecho();
* * curs_set(0);
* * start_color();
* * timeout(100);
* * set_escdelay(0);
* * keypad(stdscr, TRUE);
* * mousemask(ALL_MOUSE_EVENTS, NULL);
* * cbreak();
* * leaveok(stdscr,false);
* * nonl();
я стараюсь подключать плюшки по мере моих потребностей,ведь даже в мышке у меня тут потребностей нет(хотя мб изза этого у меня так коряво и пошло)
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
move(0,0); //чтобы начать отрисовку с угла
после erase и refresh он туда и становится-т.е. они не нужны?
P.S.:Я понимаю что сегодня выходной,так что большое спасибо за быстрый ответ
Миниатюры
Прошу критики игры "Змейка"   Прошу критики игры "Змейка"  
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
04.08.2018, 10:41  [ТС]
(заполнил поле буквами q для наглядности)
0
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
04.08.2018, 16:31
Цитата Сообщение от anton3d Посмотреть сообщение
при добавлении \n получается какая-то лажа,лично на моем терминале это выглядит так(прикреплю скрины внизу)
Автоперевод строки при достижении края. Можно сделать явное move(), а можно уменьшить поле до 79 символов.
Цитата Сообщение от anton3d Посмотреть сообщение
Хотел еще управлять размерами окна,или даже создать со своими параметрами(но у меня не получилось((()
Напрямую управлять размерами окна из программы нельзя. Представьте себе аппаратный терминал - тот что с монохромным зеленым экраном и клавиатурой без стрелок (ну или загуглите знаменитый vt100). У него уж какой есть экран, такой есть. Но можно вывести надпись "изменить размер окна хотя бы до 80х25; сейчас у вас 100х20") и пусть пользователь подгоняет размер под минимально достаточный.
Цитата Сообщение от anton3d Посмотреть сообщение
я стараюсь подключать плюшки по мере моих потребностей,ведь даже в мышке у меня тут потребностей нет(хотя мб изза этого у меня так коряво и пошло)
Эти настройки я бы посоветовал оставить как есть. То что не нужно так и не используйте, зато то что нужно будет работать правильно. По крайней мере для корректного ввода клавиш половина этих настроек необходима.
Цитата Сообщение от anton3d Посмотреть сообщение
после erase и refresh он туда и становится-т.е. они не нужны?
Да, erase и refresh в данном случае не нужны.
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
05.08.2018, 16:48  [ТС]
COKPOWEHEU, У меня получается))
Вот первая рабочая версия с curses:
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
#include <curses.h>
#include <cstdlib>
#include <ctime>
 
bool game_status;
char field[24][80],head,tail,food,direction,last_direction;
int head_pos_x,head_pos_y,last_head_pos_x[100],last_head_pos_y[100],food_position_x,food_position_y,key,score,counter,length;
 
void set_food(){
    do{
    food_position_x = rand() % 78 + 1;
    food_position_y = rand() % 22 + 1;
    }while(field[food_position_y][food_position_x] != ' ');
    field[food_position_y][food_position_x] = food;
}
 
void draw(){
    move(0,0); //чтобы начать отрисовку с угла
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j)addch(field[i][j]);
        move(i+1,0);//перевод строки
    }
    printw("SCORE: %i", score);
    printw(" ");
    printw("CURRENT DIRECTION: %c", direction);
    printw(" ");
    printw("FOOD POSITION x: %i", food_position_x);
    printw(" ");
    printw("FOOD POSITION y: %i", food_position_y);
}
 
void check_input(){
    key = getch(); //ввод символа
    last_direction = direction;
    switch (key){
        case KEY_DOWN:
            if (last_direction != 'U')direction = 'D';
            break;
        case KEY_UP:
            if (last_direction != 'D')direction = 'U';
            break;
        case KEY_LEFT:
            if (last_direction != 'R')direction = 'L';
            break;
        case KEY_RIGHT:
            if (last_direction != 'L')direction = 'R';
            break;
    }
}
 
void init(){
    for (int i = 0; i < 24; ++i){for (int j = 0; j < 80; ++j)field[i][j]=' ';}
    for (int i = 0; i < 24; ++i)field[i][0] = '#';
    for (int i = 0; i < 24; ++i)field[i][79] = '#';
    for (int i = 1; i < 80; ++i)field[0][i] = '#';
    for (int i = 1; i < 80; ++i)field[23][i] = '#';
    score = 0;
    head = '@';
    tail = 'o';
    food ='O';
    head_pos_x = 15;
    head_pos_y = 11;
    counter = 0;
    length = 3;
    srand(time(NULL));
    set_food();
    game_status = true;
}
 
void move(){
    field[last_head_pos_y[counter - 1]][last_head_pos_x[counter - 1]] = ' ';
    field[0][0] = '#';//код вроде новый,а костыли старые :D
    last_head_pos_x[counter - 1] = head_pos_x;
    last_head_pos_y[counter - 1] = head_pos_y;
    switch (direction)
    {
    case 'L'://влево
        head_pos_x -= 1;
        break;
    case 'R'://вправо
        head_pos_x += 1;
        break;
    case 'D'://вниз
        head_pos_y += 1;
        break;
    case 'U'://вверх
        head_pos_y -= 1;
        break;
    }field[last_head_pos_y[counter - 1]][last_head_pos_x[counter - 1]] = tail;
    if (length == counter) {
        for (int i = 1; i <= length; ++i)field[last_head_pos_y[counter - i]][last_head_pos_x[counter - i]] = tail;
    }
    if (counter == length)counter = 0;
    ++counter;
}
 
void check_position(){
    if (field[head_pos_y][head_pos_x] == '#')game_status = false;
    if (field[head_pos_y][head_pos_x] == food){
        ++score;
        ++length;
        set_food();
    }
}
 
void update(){
    move();
    check_input();
    check_position();
    field[head_pos_y][head_pos_x]=head;
}
 
int main(){
    initscr();
    noecho();
    curs_set(0);
    start_color();
    timeout(100);
    set_escdelay(0);
    keypad(stdscr, TRUE);
    mousemask(ALL_MOUSE_EVENTS, NULL);
    cbreak();
    leaveok(stdscr,false);
    nonl();
    init();
    while(game_status){
        draw();
        update();
    }
    endwin();
    return 0;
}
Переписал старый код и механика поворота стала адекватной-это не может не радовать))))
Из старых косяков остался исчезающий уголок.
И игра больше не будет мигать)))))))))
Хоть это и пока что черновой вариант и еще кучу всего нужно доделать,но я уже счастлив от того как круто все получается!
Вложения
Тип файла: rar Snake.rar (126.1 Кб, 1 просмотров)
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
05.08.2018, 16:50  [ТС]
COKPOWEHEU, Что можете сказать по поводу кода?
И еще у меня была идея,которую в старом коде не успел реализовать-звук.
Хочется добавить минимальный *бип* в момент когда змея кушает еду,в начале и конце игры.
Что можете посоветовать?
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,028
Записей в блоге: 242
05.08.2018, 18:44
Цитата Сообщение от anton3d Посмотреть сообщение
механика поворота стала адекватной
Наверное, я давно не играл в змейку, подолгу не могу съесть еду, кружу вокруг неё.

Цитата Сообщение от anton3d Посмотреть сообщение
Хочется добавить минимальный *бип* в момент когда змея кушает еду
А следующая ступень может быть - добавление фоновой музыки.

Над переносом игры на OpenGL пока не задумывались?
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
05.08.2018, 20:15  [ТС]
COKPOWEHEU, Я доделал внешний вид до конца-вот код:
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
#include <curses.h>
#include <cstdlib>
#include <ctime>
#include <fstream>
 
bool game_status;
char field[24][80],head,tail,food,direction,last_direction;
int head_pos_x,head_pos_y,last_head_pos_x[100],last_head_pos_y[100],food_position_x,food_position_y,key,score,counter,length,highscore;
unsigned int start_time, search_time, end_time;
 
void set_food(){
    do{
    food_position_x = rand() % 78 + 1;
    food_position_y = rand() % 22 + 1;
    }while(field[food_position_y][food_position_x] != ' ');
    field[food_position_y][food_position_x] = food;
}
 
void draw(){
    move(0,0); //чтобы начать отрисовку с угла
    for (int i = 0; i < 24; ++i) {
        for (int j = 0; j < 80; ++j){
            if(field[i][j] == food)addch(field[i][j] | A_BOLD | COLOR_PAIR(2));else{
                if(field[i][j] == head)addch(field[i][j] | A_BOLD | COLOR_PAIR(3));else{
                    if(field[i][j] == tail)addch(field[i][j] | COLOR_PAIR(3));else
                    addch(field[i][j] | A_BOLD | COLOR_PAIR(1));
                }
            }
        }
        move(i+1,0);//перевод строки
    }
    attrset(A_BOLD);
    printw("SCORE: %i", score);
    printw(" ");
    printw("HIGHSCORE: %i", highscore);
    printw(" ");
    printw("TIME: %5.1f", search_time / 1000.0);
    printw("s");
    attrset(A_NORMAL);
}
 
void check_input(){
    key = getch(); //ввод символа
    last_direction = direction;
    switch (key){
        case KEY_DOWN:
            if (last_direction != 'U')direction = 'D';
            break;
        case KEY_UP:
            if (last_direction != 'D')direction = 'U';
            break;
        case KEY_LEFT:
            if (last_direction != 'R')direction = 'L';
            break;
        case KEY_RIGHT:
            if (last_direction != 'L')direction = 'R';
            break;
    }
}
 
void init(){
    std::ifstream in("highscore.txt");//подключаем файл с рекордом,если таковой имеется
    in >> highscore;//считываем рекорд
    in.close();
    noecho();
    curs_set(0);
    start_color();
    init_pair(1, COLOR_BLUE, COLOR_BLACK);
    init_pair(2, COLOR_RED, COLOR_BLACK);
    init_pair(3, COLOR_GREEN, COLOR_BLACK);
    init_pair(4, COLOR_WHITE, COLOR_BLACK);
    timeout(100);
    set_escdelay(0);
    keypad(stdscr, TRUE);
    mousemask(ALL_MOUSE_EVENTS, NULL);
    cbreak();
    leaveok(stdscr,false);
    nonl();
    for (int i = 0; i < 24; ++i){for (int j = 0; j < 80; ++j)field[i][j]=' ';}
    for (int i = 0; i < 24; ++i)field[i][0] = '#';
    for (int i = 0; i < 24; ++i)field[i][79] = '#';
    for (int i = 1; i < 80; ++i)field[0][i] = '#';
    for (int i = 1; i < 80; ++i)field[23][i] = '#';
    start_time = clock();
    search_time = 0;
    score = 0;
    head = '@';
    tail = 'o';
    food ='O';
    head_pos_x = 15;
    head_pos_y = 11;
    counter = 0;
    length = 3;
    srand(time(NULL));
    set_food();
}
 
void move(){
    field[last_head_pos_y[counter - 1]][last_head_pos_x[counter - 1]] = ' ';
    field[0][0] = '#';//код вроде новый,а костыли старые :D
    last_head_pos_x[counter - 1] = head_pos_x;
    last_head_pos_y[counter - 1] = head_pos_y;
    switch (direction)
    {
    case 'L'://влево
        head_pos_x -= 1;
        break;
    case 'R'://вправо
        head_pos_x += 1;
        break;
    case 'D'://вниз
        head_pos_y += 1;
        break;
    case 'U'://вверх
        head_pos_y -= 1;
        break;
    }field[last_head_pos_y[counter - 1]][last_head_pos_x[counter - 1]] = tail;
    if (length == counter) {
        for (int i = 1; i <= length; ++i)field[last_head_pos_y[counter - i]][last_head_pos_x[counter - i]] = tail;
    }
    if (counter == length)counter = 0;
    ++counter;
}
 
void check_position(){
    if (field[head_pos_y][head_pos_x] == '#')game_status = false;
    if (score != 0 && field[head_pos_y][head_pos_x] == tail)game_status = false;
    if (field[head_pos_y][head_pos_x] == food){
        ++score;
        ++length;
        set_food();
    }
}
 
void update(){
    move();
    check_input();
    check_position();
    end_time = clock();
    search_time = end_time - start_time;
    field[head_pos_y][head_pos_x]=head;
}
 
void menu(){
    attron(A_BOLD | COLOR_PAIR(3));
    addstr("                       ______                _            \n" );
    addstr("                      / _____)              | |           \n" );
    addstr("                     ( (____   ____   _____ | |  _  _____ \n" );
    addstr("                      \\____ \\ |  _ \\ (____ || |_/ )| ___ |\n" );
    addstr("                      _____) )| | | |/ ___ ||  _ ( | ____|\n" );
    addstr("                     (______/ |_| |_|\\_____||_| \\_)|_____)\n" );
    addstr("                                                          \n" );
    attron(A_BLINK |COLOR_PAIR(4));
    addstr("                         Press ENTER to start new game\n");
    while (true) {
        key = getch();
        if (key == 13) {
            game_status = true;//запускаем игру
            attrset(A_NORMAL);
            break;
        }
    }
}
 
void end_game(){
    clear();
    attron(A_BOLD | COLOR_PAIR(3));
    addstr("                       ______                _            \n" );
    addstr("                      / _____)              | |           \n" );
    addstr("                     ( (____   ____   _____ | |  _  _____ \n" );
    addstr("                      \\____ \\ |  _ \\ (____ || |_/ )| ___ |\n" );
    addstr("                      _____) )| | | |/ ___ ||  _ ( | ____|\n" );
    addstr("                     (______/ |_| |_|\\_____||_| \\_)|_____)\n" );
    addstr("                                                          \n" );
    printw("\n");
    if (score > highscore) {
        highscore = score;
        attron(A_BOLD | COLOR_PAIR(4));
        printw("                           Your new highscore: ");
        attron(A_BOLD | COLOR_PAIR(2));
        printw("%i", highscore);
        printw("\n");
        printw("\n");
        std::ofstream out("highscore.txt");
        out << highscore;
        out.close();
    }
    attron(A_BLINK | A_BOLD | COLOR_PAIR(4));
    addstr("                     Press ENTER to restart,or ESC to exit");
    do {
        key = getch();
        if (key == 13) {
            game_status = true;
            direction = ' ';
            attrset(A_NORMAL);
        }
    } while ((key != 27) and (key != 13));
}
 
int main(){
    
    initscr();
    init();
    menu();
    while(game_status){
        init();
        while(game_status){
            draw();
            update();
        }
        end_game();
    }
    endwin();
    return 0;
}
Стены не получилось сделать-curses конфликтует с ascii кодами(или,что вероятнее я не правильно их использовал,хз)
Изображения
 
Вложения
Тип файла: rar Snake.rar (491.1 Кб, 0 просмотров)
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
05.08.2018, 20:18  [ТС]
8Observer8,
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Наверное, я давно не играл в змейку, подолгу не могу съесть еду, кружу вокруг неё.
Точно Вам говорю-стало в разы лучше.
Цитата Сообщение от 8Observer8 Посмотреть сообщение
А следующая ступень может быть - добавление фоновой музыки.
Думаю для этой игры это лишнее,*бипа* будет достаточно)
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Над переносом игры на OpenGL пока не задумывались?
Я уже почти доделал этот вариант с curses,как закончу-буду решать opengl,dx,может быть движок начну учить,над этим я еще подумаю)
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,028
Записей в блоге: 242
05.08.2018, 22:48
Цитата Сообщение от anton3d Посмотреть сообщение
Думаю для этой игры это лишнее,*бипа* будет достаточно)
Да, я тоже так подумал. Когда заходите начать переправлять свой код со змейкой под чистый OpenGL, то лучше берите для окна и ввода/вывода: SDL2 или SFML, потому что они имеют dll для удобноый работы со звуком. Если что-то другое возьмёте для окна: GLFW, FreeGlut, WinAPI, Qt и т.д., то можно взять универсальную библиотеку для звука, к примеру, OpenAL, но с ней дольше разбираться. Читал, что Irrklang удобная и универсальная. Есть много разных библиотек для звука, есть из чего выбирать. Универсальные библиотеки это те, которые подходят и для OGL и для DX.
1
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
06.08.2018, 09:27
C
1
2
3
4
5
6
7
8
9
for (int i = 0; i < 24; ++i) {
    for (int j = 0; j < 80; ++j){
      if(field[i][j] == food)addch(field[i][j] | A_BOLD | COLOR_PAIR(2));else{
        if(field[i][j] == head)addch(field[i][j] | A_BOLD | COLOR_PAIR(3));else{
          if(field[i][j] == tail)addch(field[i][j] | COLOR_PAIR(3));else
            addch(field[i][j] | A_BOLD | COLOR_PAIR(1));
        }
      }
    }
Не проще было закодировать поле массивом int и встроить туда все атрибуты?
C
1
2
3
4
5
6
7
8
int food ='O' | A_BOLD | COLOR_PAIR(2);
...
field[food_position_y][food_position_x] = food;
...
for (int i = 0; i < 24; ++i) {
  for (int j = 0; j < 80; ++j)addch(field[i][j]);
  move(i+1,0);//перевод строки
}
Цитата Сообщение от anton3d Посмотреть сообщение
Думаю для этой игры это лишнее,*бипа* будет достаточно)
Теоретически должен работать вывод символа '\a', но у меня все эти бесячие пищалки отключены.
Совет по объектам так и остался невостребованным.
Не нашел где настраивается скорость. Полагаться на timeout(100); не лучшая идея.

Добавлено через 13 минут
Ах да, еще одно. Вместо перерисовки всего экрана можно затирать клетку за хвостом змейки. Тогда отрисовка будет выглядеть так:
C++
1
2
3
4
5
6
7
8
9
void Snake::draw(){
  for(int i=1; i<len-1; i++)field[ pos[i].x ][ pos[i].y] ] = SNAKE_BODY;
  field[ pos[0].x ][ pos[0].y ] = SNAKE_HEAD;
  field[ pos[len-1].x ][ pos[len-1].y ] = SNAKE_TAIL;
  field[ pos[len].x ][ pos[len].y ] = FIELD_EMPTY;
}
void draw(){
  snake.draw();
}
0
2 / 2 / 0
Регистрация: 08.06.2018
Сообщений: 66
06.08.2018, 18:06  [ТС]
COKPOWEHEU,
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Не проще было закодировать поле массивом int и встроить туда все атрибуты?
Я думал,только символы типа chtype можно кодировать,разве не так?
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Совет по объектам так и остался невостребованным.
какой?
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Не нашел где настраивается скорость. Полагаться на timeout(100); не лучшая идея.
Для этой игры вполне достаточно)
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Ах да, еще одно. Вместо перерисовки всего экрана можно затирать клетку за хвостом змейки. Тогда отрисовка будет выглядеть так:
А это я попробую,большое спасибо)
0
 Аватар для COKPOWEHEU
4093 / 2691 / 432
Регистрация: 09.09.2017
Сообщений: 11,983
07.08.2018, 11:42
Цитата Сообщение от anton3d Посмотреть сообщение
Я думал,только символы типа chtype можно кодировать,разве не так?
В компьютере все - байты. Остальное - интерпретация конкретными функциями.
Лучше посмотрите какой тип принимает функция addch() - в таком можно и хранить.
Цитата Сообщение от anton3d Посмотреть сообщение
какой?
Завернуть данные, относящиеся к одному объекту в один объект. Ту же змейку, еду, поле, ввод-вывод
Цитата Сообщение от anton3d Посмотреть сообщение
Для этой игры вполне достаточно)
Попробуйте зажать одну клавишу - змейка будет ползти быстрее. Это дает неравномерность движения и ухудшает предсказуемость. Кстати, было бы интересно услышать ваше мнение относительно причин этого феномена.
Кроме того, человеческая реализация игрового цикла с ограничением времени (первый способ) или подстройкой скорости анимации (второй) это полезный опыт.

Добавлено через 30 минут
end_time = clock();
Это далеко не самая точная штука, можете сами проверить.
Вместо этого я обычно использую такую функцию:
C
1
2
3
4
5
6
7
8
9
#include <sys/time.h>
//получить время в миллисекундах (большая точность все равно вряд ли пригодится)
unsigned long get_time_ms(){
  struct timeval tv;
  unsigned long time_ms;
  gettimeofday(&tv,NULL);
  time_ms = tv.tv_usec/1000 + tv.tv_sec*1000;
  return time_ms;
}
А с помощью отсчета времени можно добавить задержку в каждую итерацию игрового цикла. Я бы посоветовал снизить таймаут ncurses'а до минимального значения, а вместо этого ограничить скорость основного цикла.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.08.2018, 11:42
Помогаю со студенческими работами здесь

Прошу вашей критики
Народ, всем привет, в общем я только начал изучать верстку. Взял шаблон вот тут: Хотел сделать резиновую верстку, но остановился...

Прошу критики и рекомендаций
Уважаемые форумчане! Выношу на ваш суд свою БД. Раньше я никогда не занималась созданием баз, но рискнула взять на себя такую...

Прошу критики от профессионалов...
Все время работал с классическим html, но решил попробовать блогинг. Создал блог 29 января 2012 - сами видите-еще зародыш, но не успел...

Прошу критики моего списка
Я написал код, но я новичок, уверен, что в нем есть косяки. Например, как написать список, чтобы по нему можно было пройтись циклом...

Прошу критики веб-дизайна
Занимаюсь самообучением веб-дизайну. Хочу услышать адекватную критику и советы. Знаю, что еще очень многое не умею, но хотелось бы...


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации: В классе Работник добавить: накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни коэффициентПрезентеизма — снижает продуктивность. . .
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день. Для работы необходим браузер,. . .
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано. . . .
Как я стал коммунистом))) Модель сохранения здоровья сотрудников, запись блога номер 15
anaschu 23.05.2026
Внезапно хорошее здоровье сотрудников не нужно капиталистам?))
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru