Предисловие
Видеоигры на протяжении уже более 30 лет активно развиваются, начиная от геймплея и графических возможностей, вплоть до продвинутых систем искусственного интеллекта и восприятия пользователями подаваемого разработчиками материала. Киберспорт, в свою очередь, является полноценным видом спорта с многомиллионными призами и миллиардными оборотами. А сама индустрия видеоигр неустанно набирает обороты, являясь одной из наиболее кассовых и массовых ответвлений сферы развлечений. А ко всему этому человечество пришло от примитивнейшей реализации «тенниса», запускавшейся на осциллографе.
Я, как первокурсник, решил в рамках изучения базовых консольных возможностей C/C++ возможно запрограммировать "классическую" ASCII-игру, требующую от игрока скорости мышления, непрерывного взаимодействия с игрой, а также обладающую несложной графической частью, которую игрок мог бы интерпретировать в некое подобие трехмерного изображения.
Несмотря на визуальную примитивность подобных решений, они безусловно вызывают у игроков ностальгию по олдскульным играм.
Вдохновление
На заре появления на рынке мобильных телефонов с монохромными дисплеями выделилась игра «Space Impact», прошивавшаяся в аппаратах Nokia. Она отлично вписалась в ограниченные возможности тогдашних сотовых. После введения простых игр в мобильные телефоны – продажи аппаратов резко возросли, а мобильный гейминг постепенно стал популярным, и сейчас вполне конкурирует со индустрией «взрослых» ААА-проектов.
«Space Impact» и послужила основой для моей первой игры ввиду своей легкости исполнения и популярности в начале 2000-х.
Особенности «Space Invader»
В первую очередь – легковесность программы. Исполняемый файл занимает менее 100 кб и будет работать, как задумано, практически на любом компьютере под OC Windows с пакетом Visual C++.
Во-вторых, переносимость — исходный код можно за несколько минут переделать под POSIX-системы, тем самым обеспечив работоспособность на UNIX и Mac операционных системах, лишь заменив несколько функций и пересобрав программу на соответствующем компиляторе.
Третье преимущество — программа портативна, не требует никаких дополнительных файлов. Все дополнительные файлы при необходимости создаются автоматически в каталоге местонахождения исполняемого файла.
Наипростейший интуитивно понятный интерфейс, не требующий описания или инструкций по использованию.
- Главное меню из 4-х пунктов, выбирать которые можно с помощью стрелок на клавиатуре.
- Пункт «Игра» — открывает меню их двух пунктов:
- Подпункт «Новая игра» — запускает новый игровой сеанс.
- Подпункт «Продолжить» — загружает последнюю сохраненную игру из бинарного файла в директории исполняемого файла и запускает игровой сеанс с использованием полученных данных.
- Пункт «Помощь» — инструкции по работе с приложением и его описание. Пролистываются по нажатию стрелок на клавиатуре.
- Пункт «Зал славы» — список лидеров игровых сессий, загружается из бинарного файла в директории исполняемого файла и форматированно выводится в консоль.
- Пункт «Выход» — выход из приложения.
- Сдвигающийся влево «мир» с динамической скоростью. «Мир» содержит рандомные поля сверху и снизу толщиной в 1 или 2 символа. Также между полями рандомно появляется «космический мусор», отображаемый символом «¤», являющийся препятствием для игрока.
- Прижатый к левому краю окна «космический корабль». Корабль смещается с помощью стрелок на клавиатуре вверх и вниз, по нажатию пробела выпускает снаряд, уничтожающий «космический мусор» по касанию.
- «Приборная панель» вверху консоли, отображающая пройденный километраж, текущую скорость и количество оставшихся попыток.
Как работает «Space Invader»?
При запуске приложения возникает заставка-анимация. Она состоит из 6 заранее отформатированных символьных массивов, сменяющихся через каждые 200мс.
Начальная заставка – итоговый слайд
Далее идет обращение в функцию главного меню с параметром 1(целое число). Функция отображает меню с выделенным угловыми скобками пунктом меню, номер которого совпадает с входным параметром. Пунктов в меню 4, соответственно входной параметр может различаться от 1 до 4. При нажатии стрелки вниз происходит рекурсивное обращение с инкрементированным входным параметром в том случае, если входной параметр меньше 4, с параметром 1, если входной параметр равен 4. При нажатии Space или Enter происходит обращение к функции, соответствующей выделенному пункту меню.
void StartMenu(int switcher)
{
system("cls");
switch (switcher)
{
case 1:
cout << "\n\n\n << ИГРАТЬ! >>\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n ВЫХОД";
break;
case 2:
cout << "\n\n\n ИГРАТЬ!\n\n << ПОМОЩЬ! >>\n\n ЗАЛ СЛАВЫ\n\n ВЫХОД";
break;
case 3:
cout << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n << ЗАЛ СЛАВЫ >>\n\n ВЫХОД";
break;
case 4:
cout << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n << ВЫХОД >>";
break;
}
int choice = _getch();
if (choice == 224)
choice = _getch();
if (choice == 72)
if (switcher != 1)
StartMenu(switcher - 1);
else
StartMenu(4);
if (choice == 80)
if (switcher != 4)
StartMenu(switcher + 1);
else
StartMenu(1);
if (choice == 13 || choice == 32)
{
if (switcher == 1)
GameMenu(1);
if (switcher == 2)
Help(0);
if (switcher == 3)
TopChart();
if (switcher == 4)
_exit(0);
}
}
Главное меню (вход в функцию выполнен с параметром 1)
При обращении к функции, соответствующей пункту «Игра» запускается функция, аналогичная по функционалу, но выбор есть только из 2-х пунктов. Соответственно, входной параметр будет 1 или 2, и при нажатии любой из стрелок (вверх или вниз) нам необходимо лишь сменить цифру на «противоположную». Наиболее оптимизированным будет вариант отнимания входного параметра от 3 (3 – 1 = 2, 3 – 2 = 1).
void GameMenu(int switcher)
{
system("cls");
if (switcher == 1)
cout << "\n\n\n\n\n << НОВАЯ ИГРА! >>\n\n ПРОДОЛЖИТЬ!";
else
cout << "\n\n\n\n\n НОВАЯ ИГРА!\n\n << ПРОДОЛЖИТЬ! >>";
int choice = _getch();
if (choice == 224)
choice = _getch();
if (choice == 72 || choice == 80)
GameMenu(3 - switcher);
if (choice == 27)
StartMenu(1);
if (choice == 13 || choice == 32)
Game(switcher);
}
Дополнительное меню (вход в функцию выполнен с параметром 1)
Теперь к основному – процессу игры. При выборе подпункта «Новая игра» — запускается новый игровой сеанс. Создается двумерный массив, размерностью 14 строк на 50 столбцов. Первая строка выделяется под приборную панель. Первый прибор – количество пройденных километров, оно равно количеству обновлений консоли (изначально консоль обновляется раз в 80мс, с каждым обновлением этот параметр декрементируется, пока не достигнет значения 25).
int odometerBuf = odometer, odometerDigitLength;
for (odometerDigitLength = 0; odometerBuf != 0; odometerBuf /= 10, odometerDigitLength++);//вычисление количества цифр на одометре
for (int i = odometerDigitLength, odometerBuf = odometer; i >= 0; i--, scr[0][i] = odometerBuf % 10 + '0', odometerBuf /= 10);//прорисовка одометра на приборную панель
scr[0][odometerDigitLength++] = 'К'; scr[0][odometerDigitLength++] = 'М';//дописывание "КМ"
odometer++;//наращение одометра
Второй прибор, текущая скорость, являет собой формулу — 1000/скорость обновления консоли. Скорость измеряется в километрах в секунду. Таким образом, изначально корабль движется со скоростью 12км/с, и через некоторое время достигает отметки в 40 км/с.
speed = 1000 / timer;//обновление спидометра
int speedBuf = speed;
for (int i = 42; speed != 0; i--, scr[0][i] = speed % 10 + '0', speed /= 10);//прорисовка спидометра на приборную панель
scr[0][42] = 'К'; scr[0][43] = 'М'; scr[0][44] = '/'; scr[0][45] = 'С';//дописывание "КМ/С"
Третий прибор отображает количество оставшихся попыток, изначально их 3. Попытки отображаются символом «&».
for (int i = 50; lifes > 0; i--, lifes--, scr[0][i] = '&');
Приборная панель в начале игрового сеанса
Следующие 2 строки, как и последние 2 – являются полями игры. Декорации полей выбираются случайным образом, могут состоять из 3-х символов или пробела. Крайние строки всегда полностью заполнены, а вторая и предпоследняя содержит символы, отличные от пробела лишь в тех местах, где эти символы «растут» из других.
char borderSymbols[] = { '†', '‡', '¤', ' ' };
for (int aboveBelow = 0; aboveBelow < 50; aboveBelow++)//прорисовка верхнего и нижнего полей (2 + 2)
{
scr[1][aboveBelow] = borderSymbols[rand() % 3];
if (scr[1][aboveBelow] == '‡')
scr[2][aboveBelow] = '¤';
scr[13][aboveBelow] = borderSymbols[rand() % 3];
if (scr[13][aboveBelow] == '‡')
scr[12][aboveBelow] = '¤';
}
Приборная панель и поля в начале игрового сеанса
В центральной строке игрового пространства, прижатым к левому краю, прорисовывается космический корабль, которым и предстоит управлять игроку.
scr[6][0] = '\\'; scr[6][1] = '\\';//прорисовка корабля
scr[7][0] = '3'; scr[7][1] = '='; scr[7][2] = '=';
scr[8][0] = '/'; scr[8][1] = '/';
Управлять ним можно стрелками вверх и вниз.
if (_kbhit())//если клавиша была нажата
{
control = _getch();//переменная примет ее значение
if (control == 224)
control = _getch();
}
if (control == 72)//при движении корабля вверх
if (scr[2][0] == '\\' || scr[3][0] == '\\' && scr[2][0] == '¤' || scr[3][1] == '\\' && scr[2][1] == '¤')//если корабль врезался в верхнее поле - игра окончена
if (lifes > 1)
{
cout << '\a';
lifes--;
weaponPos = 7;
GameStart(scr, lifes, &timer);
Sleep(1000);
}
else
GameOver(odometer);
else
{
for (int i = 2; i < 13; i++)//корабль смещается на элемент выше
for (int j = 0; j < 49; j++)
if (scr[i][j] == '3' || scr[i][j] == '\\' || scr[i][j] == '=' || scr[i][j] == '/')
{
scr[i - 1][j] = scr[i][j];
scr[i][j] = ' ';
}
weaponPos--;
}
if (control == 80)//при движении корабля вниз
if (scr[12][0] == '/' || scr[11][0] == '/' && scr[12][0] == '¤' || scr[11][1] == '/' && scr[12][1] == '¤')//если корабль врезался в нижнее поле - игра окончена
if (lifes > 1)
{
cout << '\a';
lifes--;
weaponPos = 7;
GameStart(scr, lifes, &timer);
Sleep(1000);
}
else
GameOver(odometer);
else
{
for (int i = 12; i >= 2; i--)//корабль смещается на элемент вниз
for (int j = 0; j < 49; j++)
if (scr[i][j] == '3' || scr[i][j] == '\\' || scr[i][j] == '=' || scr[i][j] == '/')
{
scr[i + 1][j] = scr[i][j];
scr[i][j] = ' ';
}
weaponPos++;
}
Расположение корабля при двукратном нажатии стрелки вверх
Отойдя от визуализации, стоит отметить, что вместе с кораблем мы смещаем вверх или вниз элемент массива, отвечающий за «дуло» корабля. Соответственно, из которого можно выпускать снаряды по нажатию пробела.
Однако, ни поле, ни снаряды не двигаются, потому, чтобы «оживить» игровой процесс, по истечению таймера перерисовки экрана «мир» будет смещаться на один столбец влево, а снаряды на один столбец вправо. Корабль же остается на месте, пока игрок не захочет иного. Но после перерисовки теперь возникает один пустой столбец – заполним его случайным образом полями и «космическим мусором», который можно сбивать снарядами или боковыми отбойниками корабля.
for (int i = 1; i < 14; i++)//все "космические" элементы смещаются на элемент влево
for (int j = 0; j < 49; j++)
{
if (scr[i][j] == '\\' && scr[i][j + 1] == '¤' || scr[i][j] == '=' && scr[i][j + 1] == '¤' || scr[i][j] == '/' && scr[i][j + 1] == '¤')
if (lifes > 1)
{
cout << '\a';
lifes--;
weaponPos = 7;
GameStart(scr, lifes, &timer);
Sleep(1000);
}
else
GameOver(odometer);
if (scr[i][j] != '3' && scr[i][j] != '\\' && scr[i][j] != '=' && scr[i][j] != '/' && scr[i][j] != '-' && scr[i][j + 1] != '-')
scr[i][j] = scr[i][j + 1];
if (scr[i][j] == '¤')
scr[i][j + 1] = ' ';
}
for (int i = 1; i < 14; i++)//все снаряды смещаются на элемент вправо
for (int j = 48; j >= 0; j--)
if (scr[i][j] == '-')
if (j != 48)
{
scr[i][j + 1] = '-';
scr[i][j] = ' ';
}
else
scr[i][j] = ' ';
char borderSymbols[] = { '†', '‡', '¤', ' ' };
scr[2][49] = ' ';//рандомное заполнение новых элементов краев
scr[1][49] = borderSymbols[rand() % 3];
if (scr[1][49] == '‡')
scr[2][49] = '¤';
scr[12][49] = ' ';
scr[13][49] = borderSymbols[rand() % 3];
if (scr[13][49] == '‡')
scr[12][49] = '¤';
for (int i = 3; i < 12; i++)//рандомное появление космического мусора
{
if (rand() % 10 == 1)
scr[i][49] = '¤';
}
При движении корабля вверх или вниз в этот момент космический мусор будет уничтожен без урона кораблю, все благодаря отбойникам
Если в данный момент не увернуться от мусора стрелкой вниз – корабль будет разбит
Снаряды, выпускаемые кораблем, сконструированы так, что сметают все на пути своего следования. Следовательно, выпустив один снаряд, расчищается коридор в одну строку.
Впрочем, хоть поля состоят из материалов, схожих на космический мусор, их нельзя разрушить отбойниками. Соприкосновение любой части корабля с полями приводит к неминуемому краху. Также, как и попадание космического мусора в лицевую часть корабля. Если в такие моменты на приборной панели есть обозначение еще хотя бы одной «попытки» — игра как будто начинается сначала, но сохранив набранный счет и потеряв одну «попытку». Скорость же сбрасывается до начального значения в 12км/с.
Если же игрок «разбился», а попыток не осталось – игровой сеанс заканчивается, а игроку предлагается ввести его имя, чтобы сохранить свой результат в «зале славы».
Предложение игроку ввести имя, чтобы сохранить свой результат в «зале славы»
Приложение обрабатывает 2 файла:
- «TopChart.bin» — двоичный файл для хранения таблицы лидеров. Данные хранятся в структурах (ник игрока, его счет, дата завершения игрового сеанса). Данные дозаписываются в конец файла при окончании игры. При вызове пункта «Зал славы» файл открывается для чтения с возможностью редактирования. Далее объявляется динамический массив структур, в который переписываются данные из файла, после чего массив сортируется и форматированно выводится в консоль (максимально возможное число результатов – 12, если массив содержит 13 результатов – последний отбрасывается после сортировки). Далее файл перезаписывается массивом структур результатов, после чего массив уничтожается.
- «CurrentSave.bin» — двоичный файл для хранения сохраненной игры. Вызывается для чтения при запуске подпункта «Продолжить» пункта «Игра». Может содержать данные для восстановления одного незавершенного игрового сеанса: номер строки, в которой содержится нос корабля, количество пройденных километров, количество оставшихся попыток, расположение обьектов на экране. С помощью этих данных формируется игровой сеанс, в точности повторяющий незавершенный. Во избежание нечестной игры, при загрузке сеанса из файла – файл удаляется. При нажатии Escape во время игры данный файл создается, и в него записываются все необходимые данные для успешного дальнейшего продолжения игрового сеанса.
Пункт главного меню «Помощь» — функция, принимающая параметр от 0 до 22, отображающая последующие 12 строк по 50 символов от входного параметра. Управление осуществляется рекурсивно с помощью стрелок вверх и вниз.
void Help(int switcher)
{
system("cls");
cout << "ПРОКРУТКА: СТРЕЛКИ ВВЕРХ/ВНИЗ | ВЕРНУТЬСЯ: ESCAPE\n";
char arr[1800] = { " УПРАВЛЕНИЕ В МЕНЮ Передвигаться по пунктам – СТРЕЛКИ ВВЕРХ/ВНИЗ Выбрать пункт – ПРОБЕЛ или ENTER Вернуться в предыдущее меню – ESCAPE УПРАВЛЕНИЕ В ИГРЕ Передвигаться вверх/вниз – СТРЕЛКИ ВВЕРХ/ВНИЗ Сделать выстрел – ПРОБЕЛ Вернуться в меню, сохранив игру – ESCAPE БРИФИНГ Вы – пилот космического корабля, попавшего в космическую бурю. Вам необходимо не разбиться и пролететь как можно большее расстояние. Корабль оборудован динамическим управлением. Чем быстрее вы летите – тем острее поворачивает судно. Корабльавтоматически постепенно разгоняется до 40 км/с. Вы можете сбивать космический мусор с помощью магнитной пушки, встроенной в судно, а также боковыми отбойниками. При управлении кораблем на щитке приборов отображается пройденная дистанция, текущая скорость и количество оставшихся «ячеек отката» (отображаются символом «&»), изначально их 3. Если решите прекратить игру – просто нажмите ESCAPE. Игра сохранится, и вы сможете ее продолжить даже после перезапуска приложения с помощью пункта «ПРОДОЛЖИТЬ!». В главном меню можно посмотреть таблицу почетных пилотов. Добейтесь своего права там оказаться! АВТОРСТВО Svjatoslav Laskov – AUTHOR Igor Marchenko – COACH National Technical University «Kharkiv Polytechnic Institute» 2016" };
for (int i = 0, buf = switcher; i < 13; i++)
{
for (int j = buf * 50; j < buf * 50 + 50; j++)
cout << arr[j];
if (i != 12)
cout << endl;
buf++;
}
int controller = _getch();//получить значение нажатой клавиши
if (controller == 224)//если была нажата стрелка
controller = _getch();//то определить какая именно
if (controller == 72)//если стрелка вверх
if (switcher > 0)
Help(switcher - 1);
else
Help(0);
if (controller == 80)//если стрелка вниз
if (switcher < 22)
Help(switcher + 1);
else
Help(22);
if (controller == 27)//если Escape
StartMenu(2);
}
Пункт главного меню «Выход» — осуществляет выход из приложения.
• УПРАВЛЕНИЕ В МЕНЮ
o Передвигаться по пунктам – СТРЕЛКИ ВВЕРХ/ВНИЗ
o Выбрать пункт – ПРОБЕЛ или ENTER
o Вернуться в предыдущее меню – ESCAPE
• УПРАВЛЕНИЕ В ИГРЕ
o Передвигаться вверх/вниз – СТРЕЛКИ ВВЕРХ/ВНИЗ
o Сделать выстрел – ПРОБЕЛ
o Вернуться в меню, сохранив игру – ESCAPE
• БРИФИНГ
Вы – пилот космического корабля, попавшего в космическую бурю. Вам необходимо не разбиться и пролететь как можно большее расстояние.
Корабль оборудован динамическим управлением. Чем быстрее вы летите – тем острее поворачивает судно. Корабль автоматически постепенно разгоняется до 40 км/с.
Вы можете сбивать космический мусор с помощью магнитной пушки, встроенной в судно, а также боковыми отбойниками.
При управлении кораблем на щитке приборов отображается пройденная дистанция, текущая скорость и количество оставшихся «ячеек отката» (отображаются символом «&»), изначально их 3.
Если решите прекратить игру – просто нажмите ESCAPE. Игра сохранится, и вы сможете ее продолжить даже после перезапуска приложения с помощью пункта «ПРОДОЛЖИТЬ!».
В главном меню можно посмотреть таблицу почетных пилотов. Добейтесь своего права там оказаться!
Итог
Лично я получил уйму удовольствия от разработки столь мелочного проекта, тем более, что стандартная консоль предназначена для вывода информации, и никак не для игр. Из-за этого фреймрейт получился очень ограничен независимо от компьютера, на котором приложение запускается.
Хотелось еще разделить приложение на несколько потоков для более корректной реакции на нажатие клавиш пользователем, но треды я реализую уже в следующем проекте на С++.
#include "conio.h"
#include "windows.h"
#include "ctime"
#include <iostream>
using namespace std;
struct player//определение структуры, хранящей данные о результатах какого-либо завершенного игрового сеанса
{
char name[7];
int score;
int mday;
int mon;
int year;
};
struct save//определение структуры, хранящей данные о незавершенном игровом сеансе
{
int weaponPos;
int timer;
int odometer;
int lifes;
char scr[14][50];
};
void ScreenOutput(char scr[14][50])//функция поэлементного вывода массива в консоль
{
system("cls");
for (int i = 0; i < 14; i++)
{
for (int j = 0; j < 50; j++)
cout << scr[i][j];
if (i != 13)
cout << endl;
}
}
//блок прототипов функций
void StartMenu(int switcher);//функция, вызывающаяся из главного меню, содержит пункты "ИГРА" и "ПРОДОЛЖИТЬ"
void GameMenu(int switcher);//функция главного меню
void GameStart(char scr[14][50], int lifes, int *timer);//функция, определяющая начальный символьный массив при запуске нового игрового сеанса
void Game(int var);//функция игровго сеанса
void GameOver(int score);//функция, спрашивающая имя игрока, и записывающая его результат в бинарный файл
void Help(int switcher);//функция помощи игроку
void TopChart();//функция "ЗАЛ СЛАВЫ" - отображает список лидеров
void Help(int switcher)
{
system("cls");
cout << "ПРОКРУТКА: СТРЕЛКИ ВВЕРХ/ВНИЗ | ВЕРНУТЬСЯ: ESCAPE\n";
char arr[1800] = { " УПРАВЛЕНИЕ В МЕНЮ Передвигаться по пунктам – СТРЕЛКИ ВВЕРХ/ВНИЗ Выбрать пункт – ПРОБЕЛ или ENTER Вернуться в предыдущее меню – ESCAPE УПРАВЛЕНИЕ В ИГРЕ Передвигаться вверх/вниз – СТРЕЛКИ ВВЕРХ/ВНИЗ Сделать выстрел – ПРОБЕЛ Вернуться в меню, сохранив игру – ESCAPE БРИФИНГ Вы – пилот космического корабля, попавшего в космическую бурю. Вам необходимо не разбиться и пролететь как можно большее расстояние. Корабль оборудован динамическим управлением. Чем быстрее вы летите – тем острее поворачивает судно. Корабльавтоматически постепенно разгоняется до 40 км/с. Вы можете сбивать космический мусор с помощью магнитной пушки, встроенной в судно, а также боковыми отбойниками. При управлении кораблем на щитке приборов отображается пройденная дистанция, текущая скорость и количество оставшихся «ячеек отката» (отображаются символом «&»), изначально их 3. Если решите прекратить игру – просто нажмите ESCAPE. Игра сохранится, и вы сможете ее продолжить даже после перезапуска приложения с помощью пункта «ПРОДОЛЖИТЬ!». В главном меню можно посмотреть таблицу почетных пилотов. Добейтесь своего права там оказаться! АВТОРСТВО Svjatoslav Laskov – AUTHOR Igor Marchenko – COACH National Technical University «Kharkiv Polytechnic Institute» 2016" };
for (int i = 0, buf = switcher; i < 13; i++)
{
for (int j = buf * 50; j < buf * 50 + 50; j++)
cout << arr[j];
if (i != 12)
cout << endl;
buf++;
}
int controller = _getch();//получить значение надатой клавиши
if (controller == 224)//если была нажата стрелка
controller = _getch();//то определить какая именно
if (controller == 72)//если стрелка вверх
if (switcher > 0)
Help(switcher - 1);
else
Help(0);
if (controller == 80)//если стрелка вниз
if (switcher < 22)
Help(switcher + 1);
else
Help(22);
if (controller == 27)//если Escape
StartMenu(2);
}
void StartMenu(int switcher)
{
system("cls");
switch (switcher)
{
case 1:
cout << "\n\n\n << ИГРАТЬ! >>\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n ВЫХОД";
break;
case 2:
cout << "\n\n\n ИГРАТЬ!\n\n << ПОМОЩЬ! >>\n\n ЗАЛ СЛАВЫ\n\n ВЫХОД";
break;
case 3:
cout << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n << ЗАЛ СЛАВЫ >>\n\n ВЫХОД";
break;
case 4:
cout << "\n\n\n ИГРАТЬ!\n\n ПОМОЩЬ!\n\n ЗАЛ СЛАВЫ\n\n << ВЫХОД >>";
break;
}
int choice = _getch();
if (choice == 224)
choice = _getch();
if (choice == 72)
if (switcher != 1)
StartMenu(switcher - 1);
else
StartMenu(4);
if (choice == 80)
if (switcher != 4)
StartMenu(switcher + 1);
else
StartMenu(1);
if (choice == 13 || choice == 32)
{
if (switcher == 1)
GameMenu(1);
if (switcher == 2)
Help(0);
if (switcher == 3)
TopChart();
if (switcher == 4)
_exit(0);
}
}
void GameMenu(int switcher)
{
system("cls");
if (switcher == 1)
cout << "\n\n\n\n\n << НОВАЯ ИГРА! >>\n\n ПРОДОЛЖИТЬ!";
else
cout << "\n\n\n\n\n НОВАЯ ИГРА!\n\n << ПРОДОЛЖИТЬ! >>";
int choice = _getch();
if (choice == 224)
choice = _getch();
if (choice == 72 || choice == 80)
GameMenu(3 - switcher);
if (choice == 27)
StartMenu(1);
if (choice == 13 || choice == 32)
Game(switcher);
}
void GameStart(char scr[14][50], int lifes, int *timer)
{
for (int i = 0; i < 14; i++)//очищение от мусора
for (int j = 0; j < 50; j++)
scr[i][j] = ' ';
for (int i = 50; lifes > 0; i--, lifes--, scr[0][i] = '&');
*timer = 80;
char borderSymbols[] = { '†', '‡', '¤', ' ' };
for (int aboveBelow = 0; aboveBelow < 50; aboveBelow++)//прорисовка верхнего и нижнего полей (2 + 2)
{
scr[1][aboveBelow] = borderSymbols[rand() % 3];
if (scr[1][aboveBelow] == '‡')
scr[2][aboveBelow] = '¤';
scr[13][aboveBelow] = borderSymbols[rand() % 3];
if (scr[13][aboveBelow] == '‡')
scr[12][aboveBelow] = '¤';
}
scr[6][0] = '\\'; scr[6][1] = '\\';//прорисовка корабля
scr[7][0] = '3'; scr[7][1] = '='; scr[7][2] = '=';
scr[8][0] = '/'; scr[8][1] = '/';
}
void GameOver(int score)
{
system("cls");
player newPlayer;//объявляние структуры
newPlayer.score = score;//инициализацие поля набранного счета
cout << "Поздравляем Вас!\nВы продержались " << score << " километров.\n\n(Пожалуйста, не используйте кириллические символы)\n(Используйте не более 6 символов)\nОставьте свое имя и станьте примером\nдля подражания будущим игрокам: ";
cin.getline(newPlayer.name, 7);//инициализацие поля имени
time_t timeCur;
time(&timeCur);
struct tm * timeCurStruct = localtime(&timeCur);
newPlayer.mday = timeCurStruct->tm_mday;//инициализацие даты завершения игры
newPlayer.mon = timeCurStruct->tm_mon;
newPlayer.year = timeCurStruct->tm_year;
FILE *topChart;
fopen_s(&topChart, "TopChart.bin", "ab+");
fwrite(&newPlayer, 1, sizeof(player), topChart);//дозапись результата в файл
fclose(topChart);
TopChart();
}
void TopChart()
{
FILE *topChart;
fopen_s(&topChart, "TopChart.bin", "rb+");
system("cls");
if (topChart == NULL)//если произошла ошибка при открытии файла
{
system("cls");
cout << "Нет ни единого результата.";
Sleep(1000);
system("cls");
cout << "Нет ни единого результата..";
Sleep(1000);
system("cls");
cout << "Нет ни единого результата...";
Sleep(1000);
cout << "\nНажмите любую клавишу, чтобы вернуться.";
_getch();
StartMenu(3);
}
fseek(topChart, 0L, SEEK_END);
int playerAmount = ftell(topChart) / sizeof(player);
player *temp = new player[playerAmount];
fseek(topChart, 0L, SEEK_SET);
for (int i = 0; i < playerAmount; i++)//копирование содержиомого файла в структкры
fread(&temp[i], 1, sizeof(player), topChart);
fclose(topChart);
for (int i = 1; i < playerAmount; i++)//сортировка структур по спаданию итоговых счетов
if (temp[i].score > temp[i - 1].score)
{
player tempAlone;
strcpy(tempAlone.name, temp[i].name);
tempAlone.score = temp[i].score;
tempAlone.mday = temp[i].mday;
tempAlone.mon = temp[i].mon;
tempAlone.year = temp[i].year;
strcpy(temp[i].name, temp[i - 1].name);
temp[i].score = temp[i - 1].score;
temp[i].mday = temp[i - 1].mday;
temp[i].mon = temp[i - 1].mon;
temp[i].year = temp[i - 1].year;
strcpy(temp[i - 1].name, tempAlone.name);
temp[i - 1].score = tempAlone.score;
temp[i - 1].mday = tempAlone.mday;
temp[i - 1].mon = tempAlone.mon;
temp[i - 1].year = tempAlone.year;
if (i > 1)
i -= 2;
else
i = 0;
}
if (playerAmount > 12)
playerAmount = 12;
cout << "№ " << "Имя" << '\t' << "Счет" << '\t' << "Дата" << endl;//вывод таблицы лидеров в консоль
for (int i = 0; i < playerAmount; i++)
{
cout << i + 1 << ')' << '\t' << temp[i].name << '\t' << temp[i].score << '\t';
if (temp[i].mday / 10 == 0)
cout << '0' << temp[i].mday;
else
cout << temp[i].mday;
cout << ' ';
switch (temp[i].mon)
{
case 0:
cout << "января";
break;
case 1:
cout << "февраля";
break;
case 2:
cout << "марта";
break;
case 3:
cout << "апреля";
break;
case 4:
cout << "мая";
break;
case 5:
cout << "июня";
break;
case 6:
cout << "июля";
break;
case 7:
cout << "августа";
break;
case 8:
cout << "сентября";
break;
case 9:
cout << "октября";
break;
case 10:
cout << "ноября";
break;
case 11:
cout << "декабря";
break;
}
cout << ' ' << 1900 + temp[i].year << endl;
}
fopen_s(&topChart, "TopChart.bin", "wb+");
for (int i = 0; i < playerAmount; i++)//запись таблицы лидеров в бинарный файл
fwrite(&temp[i], 1, sizeof(player), topChart);
fclose(topChart);
delete[] temp;
_getch();
StartMenu(3);
}
int main()
{
setlocale(LC_ALL, "Rus");//задание кодировки
system("mode con cols=51 lines=14");//задание размеров окна консоли
system("title Space Invader");//задание описания окна консоли
system("color 0A");//задание цвета консоли (0-задний фон; А-передний фон)
HANDLE hCons = GetStdHandle(STD_OUTPUT_HANDLE);//получение хендла
CONSOLE_CURSOR_INFO cursor = { 100, false };//число от 1 до 100 размер курсора в процентах; false\true - видимость
SetConsoleCursorInfo(hCons, &cursor);//применение заданных параметров курсора
int timer = 200;
cout << " (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n\n\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ( )( ( \\/ )( \\ / _\\ ( \\( __)( _ \\";//вступительная заставка
Sleep(timer);
system("cls");
cout << " \\___ \\ ) __// \\( (__ ) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ( )( ( \\/ )( \\ / _\\ ( \\( __)( _ \\\n )( / /\\ \\/ // \\ ) D ( ) _) ) /";//вступительная заставка
Sleep(timer);
system("cls");
cout << " / ___)( _ \\ / _\\ / __)( __)\n \\___ \\ ) __// \\( (__ ) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ( )( ( \\/ )( \\ / _\\ ( \\( __)( _ \\\n )( / /\\ \\/ // \\ ) D ( ) _) ) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка
Sleep(timer);
system("cls");
cout << " ____ ____ __ ___ ____\n / ___)( _ \\ / _\\ / __)( __)\n \\___ \\ ) __// \\( (__ ) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n\n\n __ __ _ _ _ __ ____ ____ ____\n ( )( ( \\/ )( \\ / _\\ ( \\( __)( _ \\\n )( / /\\ \\/ // \\ ) D ( ) _) ) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка
Sleep(timer);
system("cls");
cout << "\n ____ ____ __ ___ ____\n / ___)( _ \\ / _\\ / __)( __)\n \\___ \\ ) __// \\( (__ ) _)\n (____/(__) \\_/\\_/ \\___)(____)\n\n\n __ __ _ _ _ __ ____ ____ ____\n ( )( ( \\/ )( \\ / _\\ ( \\( __)( _ \\\n )( / /\\ \\/ // \\ ) D ( ) _) ) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка
Sleep(timer);
system("cls");
cout << "\n\n ____ ____ __ ___ ____\n / ___)( _ \\ / _\\ / __)( __)\n \\___ \\ ) __// \\( (__ ) _)\n (____/(__) \\_/\\_/ \\___)(____)\n __ __ _ _ _ __ ____ ____ ____\n ( )( ( \\/ )( \\ / _\\ ( \\( __)( _ \\\n )( / /\\ \\/ // \\ ) D ( ) _) ) /\n (__)\\_)__) \\__/ \\_/\\_/(____/(____)(__\\_)";//вступительная заставка
cout << '\a';
Sleep(10 * timer);//задержка заставки
StartMenu(1);
return 0;
}
void Game(int var)
{
int weaponPos;//позиция строки дула в массиве
int timer;//задержка между перерисовками экрана
int odometer;//количество перерисовок экрана, они же итоговые очки
int lifes;//количество жизней
char control = '&';//переменная управления кораблем
int shotPause = 4;//задержка между выстрелами (указывать на одну перерисовку больше)
int speed;//скорость корабля
char scr[14][50];
if (var == 1)
{
weaponPos = 7;//позиция строки дула в массиве
odometer = 1;//количество перерисовок экрана, они же итоговые очки
lifes = 3;//количество жизней
GameStart(scr, lifes, &timer);
}
else//при восстановлении игрового сеанса из сохранения
{
FILE *saveBin;
fopen_s(&saveBin, "CurrentSave.bin", "rb");
if (!saveBin)
{
system("cls");
cout << "Нет сохранения.";
Sleep(1000);
system("cls");
cout << "Нет сохранения..";
Sleep(1000);
system("cls");
cout << "Нет сохранения...";
Sleep(1000);
Game(1);
}
fread(&weaponPos, 1, sizeof(int), saveBin);
timer = 80;
fread(&odometer, 1, sizeof(int), saveBin);
fread(&lifes, 1, sizeof(int), saveBin);
fread(&scr, 14 * 50, sizeof(char), saveBin);
fclose(saveBin);
remove("CurrentSave.bin");
}
while (true)
{
int odometerBuf = odometer, odometerDigitLength;
for (odometerDigitLength = 0; odometerBuf != 0; odometerBuf /= 10, odometerDigitLength++);//вычисление количества цифр на одометре
for (int i = odometerDigitLength, odometerBuf = odometer; i >= 0; i--, scr[0][i] = odometerBuf % 10 + '0', odometerBuf /= 10);//прорисовка одометра на приборную панель
scr[0][odometerDigitLength++] = 'К'; scr[0][odometerDigitLength++] = 'М';//дописывание "КМ"
odometer++;//наращение одометра
speed = 1000 / timer;//обновление спидометра
int speedBuf = speed;
for (int i = 42; speed != 0; i--, scr[0][i] = speed % 10 + '0', speed /= 10);//прорисовка спидометра на приборную панель
scr[0][42] = 'К'; scr[0][43] = 'М'; scr[0][44] = '/'; scr[0][45] = 'С';//дописывание "КМ/С"
if (_kbhit())//если клавиша была нажата
{
control = _getch();//переменная примет ее значение
if (control == 224)
control = _getch();
}
if (control == 13 && shotPause == 4 || control == 32 && shotPause == 4)//при нажатии на курок если пушка перезаряжена
{
scr[weaponPos][3] = '-';
shotPause = 0;
}
if (shotPause < 4)//перезарядка
shotPause++;
if (control == 27)//при выходе
{
FILE *saveBin;
fopen_s(&saveBin, "CurrentSave.bin", "wb");
fwrite(&weaponPos, 1, sizeof(int), saveBin);
fwrite(&odometer, 1, sizeof(int), saveBin);
fwrite(&lifes, 1, sizeof(int), saveBin);
fwrite(&scr, 14 * 50, sizeof(char), saveBin);
fclose(saveBin);
GameMenu(2);
}
if (control == 72)//при движении корабля вверх
if (scr[2][0] == '\\' || scr[3][0] == '\\' && scr[2][0] == '¤' || scr[3][1] == '\\' && scr[2][1] == '¤')//если корабль врезался в верхнее поле - игра окончена
if (lifes > 1)
{
cout << '\a';
lifes--;
weaponPos = 7;
GameStart(scr, lifes, &timer);
Sleep(1000);
}
else
GameOver(odometer);
else
{
for (int i = 2; i < 13; i++)//корабль смещается на элемент выше
for (int j = 0; j < 49; j++)
if (scr[i][j] == '3' || scr[i][j] == '\\' || scr[i][j] == '=' || scr[i][j] == '/')
{
scr[i - 1][j] = scr[i][j];
scr[i][j] = ' ';
}
weaponPos--;
}
if (control == 80)//при движении корабля вниз
if (scr[12][0] == '/' || scr[11][0] == '/' && scr[12][0] == '¤' || scr[11][1] == '/' && scr[12][1] == '¤')//если корабль врезался в нижнее поле - игра окончена
if (lifes > 1)
{
cout << '\a';
lifes--;
weaponPos = 7;
GameStart(scr, lifes, &timer);
Sleep(1000);
}
else
GameOver(odometer);
else
{
for (int i = 12; i >= 2; i--)//корабль смещается на элемент вниз
for (int j = 0; j < 49; j++)
if (scr[i][j] == '3' || scr[i][j] == '\\' || scr[i][j] == '=' || scr[i][j] == '/')
{
scr[i + 1][j] = scr[i][j];
scr[i][j] = ' ';
}
weaponPos++;
}
for (int i = 1; i < 14; i++)//все "космические" элементы смещаются на элемент влево
for (int j = 0; j < 49; j++)
{
if (scr[i][j] == '\\' && scr[i][j + 1] == '¤' || scr[i][j] == '=' && scr[i][j + 1] == '¤' || scr[i][j] == '/' && scr[i][j + 1] == '¤')
if (lifes > 1)
{
cout << '\a';
lifes--;
weaponPos = 7;
GameStart(scr, lifes, &timer);
Sleep(1000);
}
else
GameOver(odometer);
if (scr[i][j] != '3' && scr[i][j] != '\\' && scr[i][j] != '=' && scr[i][j] != '/' && scr[i][j] != '-' && scr[i][j + 1] != '-')
scr[i][j] = scr[i][j + 1];
if (scr[i][j] == '¤')
scr[i][j + 1] = ' ';
}
for (int i = 1; i < 14; i++)//все снаряды смещаются на элемент вправо
for (int j = 48; j >= 0; j--)
if (scr[i][j] == '-')
if (j != 48)
{
scr[i][j + 1] = '-';
scr[i][j] = ' ';
}
else
scr[i][j] = ' ';
char borderSymbols[] = { '†', '‡', '¤', ' ' };
scr[2][49] = ' ';//рандомное заполнение новых элементов краев
scr[1][49] = borderSymbols[rand() % 3];
if (scr[1][49] == '‡')
scr[2][49] = '¤';
scr[12][49] = ' ';
scr[13][49] = borderSymbols[rand() % 3];
if (scr[13][49] == '‡')
scr[12][49] = '¤';
for (int i = 3; i < 12; i++)//рандомное появление космического мусора
{
if (rand() % 10 == 1)
scr[i][49] = '¤';
}
ScreenOutput(scr);//вывод экрана
if (control != '&')//"обнуление" управляющей переменной
control = '&';
if (timer > 25)//ускорение корабля
timer--;
Sleep(timer);//задержка перерисовки
}
}
Загрузить исполняемый файл .exe можно тут: Space Invader.
P.S.: Это мой первый проект и статья на Хабре, жду комментариев.
Комментарии (140)
SkyHunter
30.06.2016 12:17+1Автор молодец. Я вот на первом курсе вместо увлечения подобным пил пиво в парке с друзьями, о чём сейчас бесконечно жалею.
(Другое дело, что это вряд ли формат Хабра, но по мне так всё равно см. п.1.)Temirkhan
30.06.2016 12:30+1Я за 5 лет университета про C++ только в легендах слышал. Хотя как-то раз нам показывали C#… Трудное детство
Idot
30.06.2016 14:25-4Игры вообще-то именно на C++ и пишут, а не на Хаскеле.
Idot
30.06.2016 20:28Поясню: да-да это именно тот случай когда от кода требуется именно скорость (количество кадров в секунду), а не то за что хвалят Хаскель.
inborn_killer
30.06.2016 20:40Поясните ещё раз, пожалуйста, я что-то не понял.
Idot
01.07.2016 04:07Тут возмутились, что игра написана на C++, а не на каком-то новомодном языке. Хотя игры пишут именно на C++ ради скорости. Конечно, в данном случае скорость не требуется, но если он будет писать игры всерьёз то ему их все равно нужно будет писать на C++. Если игры все равно нужно писать на C++, то возмущение тем, что автор писал именно на C++ — неуместно.
Я про:Я за 5 лет университета про C++ только в легендах слышал
где C++ объявили «устаревшим ненужным динозавром», и намекнули что нужно писать на новомодном языке.Temirkhan
01.07.2016 10:37+1Эмм… Вы часом не в СМИ работаете? Я просто имел ввиду то, что C++ никогда не встречал за тяжелым детством в университете…
Idot
01.07.2016 11:11Читая Ваше сообщение можно решить, что Ваша фраза «трудное детство» написана Вами про автора, который писал на C++.
Temirkhan
01.07.2016 12:23Если Вас и вправду интересует мое мнение, я легко отношусь к любым «ошибкам», которые допускает программист, при условии, что он внимает критике и исправляется.
GamePad64
01.07.2016 02:38+2Точнее, игровые движки пишут на C++. А логику игры могут уже писать на чём угодно, от JS до Lua.
ScratchBoom
30.06.2016 12:59+6И правильно делали. Лучше пиво пить, чем такой код писать.
SkyHunter
30.06.2016 17:09+1Можно подумать, ваши первые потуги были примером для подражания. Научится ещё, всё приходит с опытом.
ZEN_UA
30.06.2016 22:24-3Я понимаю, что программа написана далеко не лучшим образом, и с радостью перепишу ее, когда получу знания о правильном форматировании проекта.
Chaos_Optima
01.07.2016 11:53+3Извините, но если вы понимаете, что программа написана плохо и вообще не несёт никакой ценности, то зачем это выкладывать на хабр? Как выше уже правильно заметили для профессионалов ценности нет, для новичков тем более ценности нет, она попросту опасна для них.
Прочтите Скотта Мейерса и что-то про ооп (только не читайте идеальный код! Пока опыта не наберётесь). Перед тем как выкладывать следующую статью.ZEN_UA
01.07.2016 13:05Данная статья не является обучающим материалом и имеет псевдоразвлекательный характер. Я приношу извинения, что Вы сочли статью неуместной, в следующий раз удостоверюсь, что все соответствует правилам чистого кода.
smartello
30.06.2016 18:50Я тоже пил пиво на горке, но ничего, к экватору устроился на работу, дважды сменил направление деятельности (оставаясь в разработке) и ни о чём не жалею. Чего и вам желаю.
monah_tuk
04.07.2016 07:41Всему своё время. На первом курсе у меня ставка за лабу по информатике была: 10 руб или бутылка пива (было тут местное — Студёное, можно было от 9 до 12 руб за бутылку найти). Пива выпил много. Да курсачи уже денежную таксу брал — к концу первого семестра таки модем смог купить и появиться в интернете (потом было несколько сростов: сначала интернет подешевке, потом и бесплатнее :)). Что бы штамповать курсачи придумалась "гибкая" архитектура — это было первым моим достижением. Она трудилась на меня почти до третьего курса. Потом благодаря пиву и левонетам я нашёл первую работу, причём сразу по суровому: embedded, C, многопоточность, голый Xlib. Всё это немного в перемешку с open source.
ЗЫ а учился на специальности Электроснабжение, информатика была на допотопных компах с Windows 3.11 и каком-то древнем визуальном бейсике.
ЗЗЫ начало учебы — 2001 год
Tujh
30.06.2016 12:24+6Поздравляю, опыт безусловно полезный, да и выкладывание на всеобщее обозрение — плюс за смелость.
Буквально пара замечаний:
1. Исходные коды лучше всего выкладывать не в саму статью, а в публичный репозиторий, например GitHub, заодно и с технологиями контроля версий, хотя бы поверхностно, познакомишься.
2. Мешать С и С++ в коде лучше отвыкать сразу.ZEN_UA
30.06.2016 22:27Спасибо за совет. Про смешивание кода имеется в виду использование FILE*?
win32asm
01.07.2016 11:14+1Использование рядом FILE* и std::cout (в смысле, стрима).
Наверное, ещё вместо 2D массива фиксированного размера (char [14][50]) лучше использовать объект, хранящий std::array, размеры 2d поля и функцию для обращения к элементу по 2м индексам (и передавать его по ссылке, где надо, и из него же читать размеры поля).
И не бояться использовать const. 8-)
Zheniog
30.06.2016 12:33+2Игра не запустилась. Не найдена либа MSVCP140D.dll. Будь я преподом, отправил бы на пересдачу :)
Nipheris
30.06.2016 12:50+12Не сочтите за грубость, ничего личного, но из-за таких преподавателей 90% людей на курсе так и не научились пользоваться C++ «в продакшене» — никто так и не рассказал, как и куда совать рантайм, как собрать релизную сборку и вообще как сделать «чтобы работало» хотя бы в одной ОС. Куча людей приходило, запускало exe-шники на компьютере препода, получало такую же ошибку и уходило печалиться со словами «а на Delphi бы написал — все б заработало». В результате преподаватели превращались из наставников в эдаких «потребителей» — объяснить ничего не могут, но надо чтобы всё работало.
Zheniog
30.06.2016 13:19-14Это универ, никто и не обязан вам все знания на блюдечке преподносить.
OnYourLips
30.06.2016 15:19+3Обязаны. В этом заключается основная задача университетов.
А «учить учиться», как любят говорить защитники скатившегося образования, обязывает наличие дееспособности, которое у здоровых людей начинается в 18 лет.Free_ze
30.06.2016 15:43+3Ни в одном образовательном стандарте не оговорено каким конкретным языкам программирования и под какую платформу программировать обучать. Есть базовые алгоритмы, есть базовые технологии. Из всего этого складывается теория. Обладая фундаментальными знаниями студент, как будущий инженер, способен **освоить** все необходимое и применить знания на практике.
А не просто «учить учиться».
Мне всегда интересно послушать предложения ненавистников «скатившегося образования» на тему «образовательной программы мечты», чтобы не потерялась ни глубина, ни универсальность и уложилось все это хотя бы в специалитет (5 лет).OnYourLips
30.06.2016 16:30-1Какая разница, какой язык используется? Если человек пишет статью, то подразумевается, что он хотя бы знает язык, на котором пишет код. При чем тут образование?
> Обладая фундаментальными знаниями студент, как будущий инженер, способен
А если не обладает? Если студенту просто не дали фундаментальные знания в должном объёме?
Если самое сложное, что проходили в вузе, были массивы и базовые алгоритмы, а на std::vector выделили всего один урок?
P.S. «Спасибо» за шестнадцатый минус в карму за этот комментарий.Free_ze
30.06.2016 17:03+3Это я к тому, что информация об отличиях дебажной версии от релизной не входит в образовательную программу по естественным причинам.
> А если не обладает?
Про структуры данных рассказали? Вот, честно, мне сложно представить, что можно рассказывать про std::vector больше одной пары.
Нам вовсе запрещали использовать контейнеры и алгоритмы STL (вообще какой-либо внешней библиотеки) для практических работ в курсе обучения основам программирования. Мы были вынуждены писать свои велосипеды, благодаря которым студенты понимали, как это реализовано внутри, по каким принципам, как это сделать оптимально. А уж узнать, что такое уже существует в стандартной библиотеке и как этим пользоваться — дело на полчаса (почитать референс).
ЗЫ Я на вашу карму влиять не могу, так что заберите свое «спасибо» обратно.
igorch96
30.06.2016 15:37+2И кому такой универ нужен? Проще самому книжки почитать и разобраться. Будет и быстрее и дешевле, да и качество знаний значительно выше, чем в таком универе…
Boletus
30.06.2016 16:05-1Люди приходят в университет и учатся. Потом начинают работать и узнают массу вещей, о которых думали иначе или не знали вообще. Я еще никогда не слышал о таком, чтобы человек пришел в университет заранее зная «как надо» (ну или хотя бы «как не надо»), и смог бы прийти к выводу как у вас (самому почитать книжки и разобраться), и этому выводу последовал.
Кроме того, университет университетом (можно самому научиться, можно и переучиться), а диплом — дипломом. Его можно либо получить, либо купить. Чтение книг его не принесет, а наличие диплома интересуют многих. И не всегда вообще у человека есть обширный выбор куда же пойти учиться.
Idot
30.06.2016 17:09+3Универ даёт гарантированную стандартную теоретическую базу. А при самостоятельном изучении есть большой соблазн эту базу пропустить.
xenohunter
30.06.2016 19:29+1У меня не техническое образование, но, научившись по книгам и статьям, работаю программистом, и соблазн для меня как раз в обратном — изучить эту самую стандартную теоретическую базу.
Free_ze
30.06.2016 19:38+2Это не соблазн. Вы ее уже пропустили. А теперь нужда тянет вас ее учить.
xenohunter
01.07.2016 11:56Вовсе нет. Frontend-разработчикам редко нужна, например, физика. Или теория чисел. И, несмотря на то, что это сложно, это ещё и дико интересно, и изучать такое — именно соблазн. И, конечно, хочется перестать быть только фронтендом.
Free_ze
01.07.2016 12:05В первом предлоджении вы говорите «вовсе нет», а в крайнем себе противоречите. Ведь если у вас есть соблазн выйти за рамки фронта, то для этого требуются новые знания. Cуть в мотивации: интересно именно заниматься чем-то другим, а не изучать прикладные науки ради изучения.
Халтура в учебе же самообоснована.xenohunter
01.07.2016 13:09+1Хм. Я понимаю вашу точку зрения, но мой посыл — в том, что обучение само по себе интересно. И базовые знания сами по себе если и требуются, то всё равно приятны в изучении.
prishelec
01.07.2016 03:28У нас в универе был курс по созданию RSS лент.
Препод сразу сказал: уже в течении двух лет когда я слышу фразу «у меня не работает», я отвечаю – и фиг с ним.
Это потом мы узнали, что он учился в аспирантуре. И ему нужно было просто проводить занятия и принять зачет.
Основная сила в самообразовании.Idot
01.07.2016 04:12Потому что когда устроишься на работу нужна будет твоя способность к самообучению (ни у кого нет времени нянчиться с новичком). А если человек привык, что за него всё разжёвывают, то…
Tujh
30.06.2016 14:00Во-первых, xxxD.dll говорит, что код отладочный, сдавать обычно всё же требуется релизную версию («как пережить релиз» очень известная статья). Во-вторых, вопрос, как отвязать программу от «redist» студии, ну или что этот пакет должен быть вместе с исполняемым файлом — вероятно второй по популярности вопрос на форумах разработки на VS. Это преподаватель не обязан объяснять, так как сильно специфичный момент, вы же не будете требовать, что бы он ещё и список библиотек для приложения написанного на Qt+MinGW рассказывал, или будете?
Я вообще за то, что бы преподаватели учили чистым языкам, а не «студиям»/«билдерам», так как объяснять потом человеку, например, что такое строки в С++ (а особенно в чистом Си) и почему нет «стандартных» IntToStr желания всё меньше и меньше.pavel_pimenov
30.06.2016 14:13+1Почему сдавать обычно требует релизную версию? в ней ведь нет assert-ов и у препода будет меньше шансов ее «уронить».
Tujh
30.06.2016 14:21Как раз релизную версию уронить легче, если она сама не упадёт по каким-то причинам. Отладочная защищает от выхода за границы массива, добавляя до и после по несколько байт «мусора», часто переменные инициируются нулём или «волшебным числом».
Я ведь не зря упомянул статью Как пережить релиз
lemelisk
30.06.2016 14:28+3нет «стандартных» IntToStr
Начиная с С++11 естьstd::to_string()
Tujh
30.06.2016 14:41+1Я как бы в курсе. А вот учебные планы — нет.
Вообще строки для многих проблема, как показывает практика. То, что в Си строка — это тот же массив байт и вот так сделать просто нельзя:
понимают далеко не все.char str1[] = "string one"; char str2[] = "string two"; char str3[] = str1 + str2
А зачем нужен std::string.c_str() и что он делает могут объяснить вообще единицы выпускников.
Nipheris
01.07.2016 03:27+1> вероятно второй по популярности вопрос на форумах разработки на VS
Да, возможно. Но этот вопрос нужно еще правильно задать. Нужно знать, ЧТО спросить.
> Я вообще за то, что бы преподаватели учили чистым языкам, а не «студиям»/«билдерам»
А кто говорит, что надо учить Студии или Билдеру? Вы не понимаете сути проблемы. Объснять надо не о том, что есть какая-то там DLL-ка у VC++-шного рантайма. Это достаточно всколзь упомянуть, добавив «ищите больше в MSDN», потратив в сумме на все это ~25 секунд. А вот что действительно нужно объяснить — что C++ как ПЛАТФОРМА (а не как язык) — вещь гибкая и разносторонняя. Что в большинстве тулчейнов есть понятие конфигурации (согласитесь, это ж не обязательно про билдер или студию). Что так или иначе существует библиотека времени выполнения, и нужно как-то с ней линковаться. Что ни malloc, ни new магическим образом не появятся в готовом бинарнике.
А про внешние библиотеки это вообще отдельная история. И тут тоже я не вижу особой зависимости от конкретного продукта IDE — всякому компилятору нужны хедеры, всякому линковщику нужны объектные файлы и файлы библиотек, и неважно какого они формата. Вы ж понимаете, что дело не в том, что студент не знает, в каком окошке в Студии include path настраивается. Студент не знает, что это в принципе НУЖНО ДЕЛАТЬ. Он не знает, что готовый бинарник нужно слинковать с каким-нибудь Qt Widgets, которым он окошки нарисовал (точнее, пытается нарисовать).
И тут встаёт вопрос — а что такое учить «чистым языкам»? Выходит, C++ как платформу тоже нужно учить? Написал и запустил — такое может и прокатит в Шарпе или Питоне, но раз преподаётся C++ — значит, нужно и цикл разработки/деплоя затронуть? Представьте что вы изучали бы C# или Java, а вам бы не стали рассказывать, что такое сборка/пакет.
В сферическом университете в вакууме конечно должна быть именно теоретическая подготовка, и курсов по конкретным ЯП вообще быть не должно. Но тогда должна быть нормальная ПРАКТИКА. Желательно на ПРОИЗВОДСТВЕ. У большинства инженерных специальностей всегда так и было. С комбайнами и станками плотно знакомились именно на заводах. А с IT у нас как сейчас? Практика есть на производстве? Мы вот за все 5 лет стен университета не покидали.
Так что нужно восполнять пробел. Как я уже выше говорил, из-за чтения C++ как «чистого языка» у нас народ так и программировал до самого диплома в лучшем случае на C# (20% максимум), еще немного PHP/Python, а все остальные так и остались на Делфи, уже тогда (в 2010 году) никому не нужном.
Только не говорите, что это эдакий «фильтр» для настоящих инженеров. Таких фильтров было и без того навалом, например когда курсы читались вообще не в том порядке, в каком надо было.Idot
01.07.2016 04:45Если вчерашнего студента взяли на работу, то предполагается что он должен уметь разбираться с подобными мелкими проблемами — САМ! Ни у кого нет времени с ним нянчиться. Так что если он научился разбираться с подобными проблемами САМ — то молодец, а иначе он будет отнимать время у своих коллег.
PS Блин! Я всем практическим навыкам обучался сам, а ВУЗе мне дали необходимую теоретическую базу и тот же многократно упоминаемый в этой теме Delphi изучил сам (тогда давали ForTran, на который мы перешли с учебно-тренировочного BASIC), да и Pascal я тоже изучил сам, и C++ и так далее. Что за блин поколение лентяев пошло?!Nipheris
01.07.2016 12:33> Ни у кого нет времени с ним нянчиться.
А вы не считаете это проблемой? Для меня «нянчится» — это когда на Тостере очередной студент копипаст код всей своей лабы и спрашивает — где у меня ошибка? Вместо того, чтобы научиться наконец дебажить, локализовать проблему и задать конкретный вопрос.
Я тоже Бейсик изучал еще с 8-го класса, а на C# начал писать еще на 1-м курсе, в то время как читали нам его на 4-м. Вопрос не в этом.
Вопрос в том, что системный подход в высшем образовании сейчас отсутствует. Мы с вами могли самостоятельно обучаться навыкам потому, что сейчас компьютеры очень доступны. И информация сейчас максимально доступна. Но вы представляете себе инженера машиностроения, который всем практическим навыкам обучается сам? Может ли он дома экспериментировать с роботом-сварщиком?) Не думаю, что у всех есть такая возможность.
То, что в IT по стечению обстоятельств имеется возможность обучаться самому не значит, что образование должно на это рассчитывать. Понимаете в чем дело, я согласен с вами что лекции в ВУЗе — это место для теории графов и алгоритмов, и даже не совсем правильно читать лекции по конкретным «языкам» — но в противном случае у студента должна быть возможность в конце каждого курса выбрать практические занятия (в универе или даже на производстве), и полноценно в них поучаствовать, чтобы наконец проложить мост между алгоритмом Дийкстры и Git-ом с MinGW и Qt.
Вообще, высшее образование сегодня выполняет немного не те задачи. Я считаю, очень сильно не хватает колледжей, которых а) хватило бы многим людям для достижения желаемого уровня навыков; б) после которых часть людей могла бы продолжить образование в ВУЗе (и тут бы остались те, кому действительно стоит получить хорошую теоретическую базу). Сейчас из-за культа полуобязательности высшего образования для инженерных специальностей масса людей приходит в ВУЗ «научиться программировать» и завтра же найти работу, а им дают алгоритмы и теорию на всю жизнь.
Про школу я вообще молчу. В соседних комментариях пишут про написание клиент-серверных игр в 11 классе — для меня это что-то совершенно невообразимое. Наш учитель по информатике не то что программировать, Винду поставить бы не смог сам. Я правда из маленького города, наверное в крупных все иначе.Idot
01.07.2016 13:04+1на Тостере очередной студент копипаст код всей своей лабы и спрашивает — где у меня ошибка?
В ДНК :)
(надеюсь помните этот анекдот)
Nipheris
01.07.2016 12:41И да, fregate хорошо сказал — неправильно и так все умеют. Программирование сейчас это все еще искусство. Очень многие вещи не формализованы и не изучены — одно разнообразие ЯП и холивары про них дают понять, что люди еще не понимают, какие инструменты для чего применять. И выходит, что в практическом плане есть очень много ремесленных секретов, вроде тех, что изложены в «Совершенном коде» Макконнела и других подобных книгах. Но такие книги полезно читать, когда ты уже набил шишек и насмотреля проблем. Студенты не будут читать такую литературу. И получается, что в идеале нужно идти на пару лет к «мастеру Джавы», и перенимать его мудрость. Вы скажете — «это называется стажировка». А я скажу, что сегодня только лучшие студенты в достаточно развитых городах могут её получать. Когда в городе нет очень крупных компаний, которые могут себе позволить взять под крыло студента, стажировок ему не видать.
Fqyeh29
30.06.2016 15:36+1Увы и у меня в вузе так. (я сам вот только только сессию 1го курса закрыл)
Есть у нас препод, задал лабы на C# и все. На вопросы «а как делать», «а где у меня ошибка?» ответ «ищи в интернете».
Вот так как то… И в итоге за 1й курс 3-4 человека освоили c#.Free_ze
30.06.2016 15:46-1И лекций по программированию у вас нет, и литературу тоже не посоветовали, да?
Idot
01.07.2016 06:29Есть у нас препод, задал лабы на C# и все. На вопросы «а как делать», «а где у меня ошибка?» ответ...
На работе с Вами тоже никто нянчиться не будет. Представьте, устроились Вы на работу и спрашиваете своего начальника «а как делать», «а где у меня ошибка?». Представили?fregate
01.07.2016 07:38+2Как-то странно преположить, что в университете не должны хотя бы показать как правильно. Как неправильно и так все умеют. Если есть ошибки, то их разбирают, если не индивидуально, то после каких-то общих лабораторных работ показывают самые распространенные и как их обходить. Преподаватель проверяет код в любом случае. А иначе… что такое обучение программированию в университете? Рассказать про базовые алгоритмы и оценку сложности их? Что дальше? Все? Программисты готовы? Можно их отправлять в продакшн? )
И странно сравнение между работой и университетом. Да, я считаю, что в универститете должны помогать разбирать ошибки, показывать как надо и как не надо и тд и тп.
В общем-то и на работе, взяв джуниора, ему также будут подсказывать и показывать, пока он не освоится с кодобазой и принципаими работы.
Temirkhan
01.07.2016 13:05-1Зачем же тогда вообще нужна песочница в виде школы и вуза? Давайте уж сразу всех в бой.
zolkko
02.07.2016 02:39+2Какой у вас злой препод. В совсем недавнем прошлом многие программировать начинали в 10-12 лет. Программы писали в тетрадках, а игрушки перепечатывали с книжек с выключенным телевизором, что бы кинескоп и зрение не садилось =]
А 18 летний дядя слишком нежен стал.
Отчислить половину группы — вторая заботает C# за вечер. Но в типовом вузе преподу никто не позволит такого сделать, времена не те.zolkko
02.07.2016 02:51-1Прям какой-то Хогвардс с Кашпировскими, ей-богу. Поставь там баночку с мочёй, а через 5 лет, глядишь, а там уже senior .net developr.
billyevans
02.07.2016 14:20+1Я приносил обычно образ виртуалки с самой виртуальной машиной, когда могли быть какие то сложности с запуском.
kx13
30.06.2016 12:44-2По поводу бинарника. Не запускается, выдает следующую ошибку:
The program can't star because MSVCP140D.dll is missing from you computer.
mikhailt
30.06.2016 12:44-3Круто! Работает!
Только вместо русских букв знаки вопроса.
Система Windows 7 x64 [Version 6.1.7601]
Free_ze
30.06.2016 12:44+16Код полон магический констант и месиво из бизнес-логики и графики. И про С++ здесь лишь I/O, в остальном здесь используется сишная стандартная библиотека. Вопрос: причем здесь хаб C++?
ЗЫ Если честно, это формат какого-нибудь Pikabu.lyubick
30.06.2016 15:36Согласен с Вами, должен отметить, что если для компиляции программы необходим g++ это не делает её программой на С++. Всё-таки хотелось бы более объектно-ориентированный поход.
Idot
30.06.2016 17:10У человека — первый блин комом. Просто надо ему помочь понять что у него не так и почему.
Free_ze
30.06.2016 17:37+1Ну почему комом? Для первого курса это неплохой результат. Но хабр — это все-таки профессиональное сообщество, где ждут статьи о чем-то инновационном или хотя бы best practices. Ценности в целой статье меньше, чем в одной ссылке со сборником таких игрушек, которую ниже приводили.
Arkafon
30.06.2016 12:44+4Собственно, а каких комментариев вы ждёте? Единственный плюс сделанной работы — доведена до конца.
Antervis
30.06.2016 13:09+1Пара настоятельных рекоммендаций:
1. Почитай c++ coding style. Их несколько, выбери по нраву и придерживайся.
2. Не используй «магические числа». Есть enum, можно задать глобальную константу (начиная с c++11 есть constexpr), на худой конец задефайни. (вытекает из п.1.)
Idot
30.06.2016 13:11-1Спасибо! Вспомнил молодость, как подобное писал на BASIC под ДОСРВ/М (Дисковая Операционная Система Реального Времени).
borisko
30.06.2016 13:16+2Даже если не придираться к стилю кода и прочим вещам, основная проблема (и я удивлён, что на неё до сих пор никто не указал) — использование рекурсии в том формате, в котором её обычно используют в ФП для передачи состояния.
Чтобы не тратить стек и не ограничивать сверху возможное время работы программы, нужно было обойтись циклом с явной обработкой текущего состояния экрана/игры или хотя бы goto.
MrMerak
30.06.2016 13:23-1— SpaceInvader.exe — Системная ошибка
— Запуск программы невозможен, так как на компьютере отсутствует MSVCP140D.dll. Попробуйте переустановить программу.
— ОК
—
barker
30.06.2016 13:36+11Почему все пишут «неплохо для первого курса»? Если это первый курс профильной специальности (кстати, судя по времени года он уже закончился), то так-то не очень.
Tujh
30.06.2016 14:04+4Я слишком давно закончил ВУЗ, но тогда профильные предметы начинались едва ли не с третьего курса. Первые — буквально азы, ни каких алгоритмов, code-style и прочего, только «пишем вот так чтобы вывести строку на экран и не задаём вопросов» (с).
Обрадуйте, что сейчас всё поменялось? :)Ddnn
30.06.2016 15:38От многих вещей зависит — от преподавателя, от направления подготовки, от вуза. У нас далеко не самая «кодерская» специальность, но даже нам на первом курсе дали некоторые простые алгоритмы и структуры данных(динамический массив и список сами писали), чуть-чуть ООП, чуть-чуть шаблонов, тонко намекнули про google coding style в конце первого семестра. Тем не менее, преподаватель хоть и упоминал иногда, как сделать хорошо, обычно пользовался логикой «ну работает и ладно».
На профильных направлениях ( вроде «Программной инженерии») материала в разы больше, и требования намного выше (даже с оформлением комментариев очень строго).
programmer4neo
30.06.2016 15:38+1К сожалению, воз и нынче там. Не смотря на смену инструментов подход по-прежнему старый. При чем как в вузах (в этом году имел удовольствие заканчивать смежную специальность и если бы не увлекался программированием со времен Делфи 3 то фиг бы что я понял), что в школах — в свежезаконченом учебном году вел профильный факультатив — сказать что программа отходы жизнедеятельности — ни сказать ничего. Простой пример попробуйте обучать С++ имея методичку по древнему паскалю в лучшем случае или по бейсику в худшем.
Labunsky
30.06.2016 20:12+1Все зависит от вуза и специальности. Имею смелость учиться на компьютерной безопасности, все основы, code-style и прочее успели подать за первые два курса, при этом для какой-нибудь джавы даже успели углубиться в тонкости вроде многопоточности. Дальше только лучше, разве что научные руководители для курсовых все так же не проявляют интереса к серьезным темам.
Взамен, такую активность многие не выдерживают, поэтому очень велик процент списывания и зубрежки вместо учебы. В итоге, к 4му курсу отсеилось больше половины потока, а из оставшихся немногие действительно разбираются в профильных предметах.
inborn_killer
30.06.2016 13:50+3Хм… По-моему, на первом курсе я программировал примерно так же. Хорошо, что в то время хабра ещё не было, а интернет был
по талонам.
BaDP1nG
30.06.2016 14:49+2А я на курсовую выходил с проектом TaxiOnMap(ещё под симбиан, был руководителем проекта). Тоже говорили, мол «зачем мобильные приложения для такси, если такси можно вызвать по телефону»? Сейчас, когда пришёл Убер, этим преподам, надеюсь, очень стыдно.)
alex-khv
30.06.2016 15:36+8Я такое в 10 классе писал. Будучи студентом (техникума в далеком мухосранске) в тетради на asm для x86 написал код змейки для граф режима 320x200*256 (удобнее чем 640x480*16 в котором байт содержит несколько пикселей). Потом в той же тетради перевел код в опкоды и на Volcov Commander в шестнадцатеричном редакторе записал опкоды в com файл. После этого дописал адреса ближнего и дальнего прыжка jpm инструкций. Это были 90е годы, только книжки и никаких интернетов.
А вы говорите автор молодец.Idot
30.06.2016 17:13-1Ну, он хотя бы хоть что-то попытался сделать сам. А то тут некоторые пишут, что ВУЗ ему должен был положить всё это в рот уже разжёванное.
Idot
30.06.2016 17:31-1PS на asm конечно круто — аплодирую Вам стоя!
(я то в школе подобное на обычном BASIC писал)roman12rus
30.06.2016 17:45-2В школе и я на BASIC для Спектрума писал, asm пытался осилить, но не допёр. Год назад поступил на второе высшее на программиста, так asm8 и asm16 вместе с С пошли отлично. Для детей написал на asm игру типа как у автора, но скроллинг вертикальный. Колбэки в JS для меня пока гораздо сложнее, чем asm. Правда, я JS меньше месяца мучаю.
Boletus
30.06.2016 15:36+1Святослав, не слушай злобных комментаторов, пиши дальше. Ну, если и не статьи, то код — точно!
Замечания и мысли.
1) Присоединюсь к тем, кто говорит что код — не С++. Его надо либо переписать на С++, либо очистить до С. Оба варианта — хорошие. Если идти по пути С, то выбрасывание С++-ной библиотеки приведет к серьезнейшему похуданию результирующего бинарника.
2) Некоторые люди не смогли запустить твою игру. У них возникла проблема с redistributable-библиотекой, потому что твоя сборка — не release, а debug, и требует иных библиотек. Почитай про это и попробуй сделать release-build.
3) Если будешь исследовать консоль Windows и дальше, то обрати внимание на позиционирование курсора. Есть в WinAPI такой вызов: SetConsoleCursorPosition (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx). С помощью него можно устанавливать курсор по координатам (x, y). В статье есть родственные вызовы, позволяющие менять цвет курсора. Можно усложнить игру, сделав разные слои — под игровое пространство, под HUD, под что-то еще.playermet
30.06.2016 22:46+1> Есть в WinAPI такой вызов: SetConsoleCursorPosition
Имхо, если делать текстовые игры под WinAPI, то лучше рисовать в буферы а затем выводить их в консоль целиком. Намного удобней организовать рисование и скорость на порядки выше.
Хорошая статья по теме: www.randygaul.net/2011/11/16/windows-console-game-writing-to-the-console
Honeysusami
30.06.2016 15:37+5Я придерживаюсь мнения, что новые статьи — есть хорошо, но они должны быть качественными. Пиши ещё, только учти все замечания.
Конкретные предложения ( некоторые высказвыались выше ):
1. Код лучше через систему контроля версий выложить куда-нибудь в open source (github наример).
2. Также ( лично моё пожелание) весь код прятать в спойлеры.
3. Смешивание чистого С и С++ надо избегать всеми силами (Кнут насколько я понмню хорошо объясняет разницу).
4. Разделения логики на уровни\компоненты\части ( вот тут можно было бы использовать ООП возможности С++ например).
5. К предыдущему пункту — разделение ( логическое ) на файлы.
6. Найти, выбрать и придерживаться определённого код-стайла.
7. Все константные числа и строки лучше организованно хранить в перечислениях \ словарях или отельных файлах (в случае локализации или внесении изменений в описании избавит от попа-боли).
8. Лучше разбивать логику на простейшие операции и выносить в отдельные фукнции и более осмысленно давать имена переменным (рекомендую почитать Р. Мартина «Чистый код»).
9. К предыдущему пункту использование больших вложенностей и рекурсий для передачи состояния.
10. Отвязка от использования платформо зависимых типов и библиотек.
abikvl
30.06.2016 17:37+1Автор, ну сделай уже нормальную релизную сборку со статически связанным рантаймом, хочу поиграться! :)
ZEN_UA
30.06.2016 23:00Сделал, жду отзыв :)
abikvl
01.07.2016 07:05Сделал, но на половину. :) По прежнему не запускается на моей машине. Я бы мог сам скачать необходимый рантайм и запустить, но в данном случае, как простой пользователь, просто жалуюсь.
Не буду комментировать качество кода, потому что, во-первых, тут уже другие постарались, во-вторых, понимание архитектуры, кодинг-стайла, как и фундаментальные знания, появятся с опытом. Но понимать, что такое линковка, чем отличается статическая библиотека от динамической, нужно уже сейчас, раз ты выкладываешь свой продукт на всеобщее обозрение.
Вот тут примерно то, что нужно сделать:
http://stackoverflow.com/questions/37398/how-do-i-make-a-fully-statically-linked-exe-with-visual-studio-express-2005
gaki
01.07.2016 05:59+1Ну я бы на первом курсе, может, и хуже написал :)
Первым делом, конечно, надо убрать все эти длиннющие строки из текста самой программы в отдельные файлы. Сделать отдельные «графические ресурсы», хоть и текстовые. Придумать структуру файлов для хранения космического корабля, меню, уровней и т. п. Читать эти данные при инициализации программы. Помимо прочего, это позволит менять данные без перекомпиляции и сильно сократит исходный код.
Во-вторых, вообще сильно сократить исходный код. За пассажи вида case 0: «октябырь», case 1: «ноябырь», по-хорошему, надо бы отрывать руки — что мешает сложить строки в массив и просто сделать cout << months[i]? Кроме того, вообще поискать в коде похожие друг на друга куски и подумать, нет ли в них чего-то общего, что можно было бы оформить в виде отдельной функции. И даже не повторяющийся код можно, для ясности, разбить на функции, согласно тому, что он делает — типа функция отрисовки корабля в позиции х, у, функция обновления спидометра и т. п.
В-третьих, чётко разделить логическое состояние игры и его отображение на экране. По-поводу того, как и зачем это сделать, можно просто открыть в википедии статью «Model-view-controller» и вдумчиво прочитать.
В-четвёртых, для общего развития попробовать портировать всё это под Линукс. Не потому, что линуксоиды тоже очень захотят поиграть, а потому, что в процессе узнаешь для себя много нового :) Если задор ещё не иссякнет, можно даже попробовать сделать так, чтобы одни и те же исходники собирались и под Линукс, и под Виндоус.
MixailPetrenko
01.07.2016 11:14А мне статья понравилась — интересно почитать, что делали другие. Я в 7-м классе изучал C++ и написал «сапёр» для командной строки.
dm_urievich
01.07.2016 11:15-1Просмотрел код, понастольгировал.
Ведь я тоже с такого кода начинал: все в числах, полно непонятных if — else, через месяц проще заново написать чем что-либо править.
Молодец, больше практики, почитай книги, прислушайся к советам в комментах и с тебя вырастет хороший программист.
vlreshet
Такое ощущение что курсовую прочитал. Мой тебе совет — убирай в черновики пока карма в минус не улетела.
simpleadmin
Человек свою курсовую не побоялся на всеобщий срач выставить. Уже это прохвально.
А что касается качества и формата статьи, то пусть и не совсем формат хабра, но в последнее время в корпоративных блогах куда хуже статьи.
vlreshet
Корпоративные статьи на то и корпоративные чтобы писать в них что захотят, ибо оплачено. Но пост с курсовой работой от первокурсника — это слишком, я считаю. Какая польза от такого поста? Кому он будет интересен?
P.S. Теперь жду пока мне сольют карму дальше. Тут же так принято — минусовать без обоснований.
simpleadmin
Если камень в мой огород, то мимо :)
GreyCat
Ну, разве что использовать как пособие «как нельзя программировать на C++ ни в коем случае». Я вот всегда признаюсь, что я C++ не знаю и не умею, но даже я представляю, что не стоит «писать на C++», если программа де факто написана на C, не стоит делать using namespace std, не стоит использовать C-подобные конструкции (вроде FILE) там, где есть C++-конструкции.
В 2016 году, казалось бы, есть auto, есть pass by reference, есть std::unique_ptr и std::shared_ptr, есть еще много чего. Отдельно забавно видеть консольное приложение, заботливо привязанное к Windows и через <windows.h>, и через system()-вызовы всяких консольных утилит cmd.exe, и rand без srand, и memory leaks (new player[] -> но нет delete). Дополнительные зведочки приложение может получить за «запихнем все в один файл», неведомый code style и комментарии на русском языке.
SkyHunter
Вы не забывайте, что автор — первокурсник.
vlreshet
Тогда опять таки возникает вопрос — зачем это на хабре? Какая польза сообществу?
1vanK
Я был согласен с Вашей точкой зрения, но потом посмотрел, что у вас вообще нет статей.
vlreshet
Чтобы сказать что суп говно — не нужно быть поваром. У меня нет статей потому что я не считаю что уже создал что-то такое о чём стоит написать в крупнейшее IT сообщество.
1vanK
Ну и зачем Вы на Хабре? Какая польза сообществу?
vlreshet
Я — это и есть сообщество. Его часть, если быть точнее. И я не обязан приносить ему пользу. А мои статьи — обязаны. Поэтому их и нет. И вообще, ваш вопрос похож на «сперва добейся».
1vanK
Конечно, но сообщество подобного рода не может писать в комментариях и критиковать других.
vlreshet
С чего это? По-вашему — комментировать и критиковать могут только те кто сам имеет статьи? Остальные же — должны молча восхвалять?
1vanK
А что, сейчас любой уже может писать в комментариях? Возможно я отстал от жизни.
Charg
Давно уже, первых 5 (вроде) комментариев на премодерации, дальше свободно.
SkyHunter
Нет, не должны, но намного лучше делать это примерно вот так, а не как вы. ИМХО.
inborn_killer
А разве что-то чрезмерно обидное было сказано? Кто-то кого-то назвал г… ном, пожелал убиться или что-то такое? По-моему, критика лишь совсем чуточку резкая, но такое можно пережить. Нет, ну правда, вы считаете, что хвалить просто за то, что «осмелился выложить» — это правильно?
1vanK
Да нет, ничего особо обидного не было. Возможно статья не рассчитана на матерых профессионалов, но для совсем уж новичков она будет полезной (я могу об этом судить хотя бы по числу закладок), а значит свою аудиторию она найдет. И еще какие-то странные аналогии с поварами. Прежде чем повара критиковать, ему заплатить надо. Просто удивляет позиция людей, которые вносят ноль импакта, но берут на себя роль модераторов, рассуждая что должно быть на Хабре, а что нет.
inborn_killer
Для профессионалов она бесполезна, а для новичков — опасна. Понимаете, эта статья — тот самый информационный шум, который мешает новичку найти по-настоящему полезную информацию. По-моему, критика здесь вполне к месту. Бывают просто слабые статьи, где действительно «автор молодец, что постарался, но надо доделать тут и тут», а бывает вот такое. Пусть студент учится и дальше, пусть у него всё хорошо в жизни сложится, но пока что рано писать статьи на хабр. Разве вы не согласны?
1vanK
Хорошо, Вы правы.
lemelisk
При чем, на мой взгляд, косяк тут в основном не автора (попытался и попытался — ничего в этом такого нету, в конце концов, деньги же за это не берут), а выдавшего за эту статью инвайт.
Robotex
Другому первокурснику польза
GreyCat
Вот это меня больше всего убивает. Это значит, что где-то же так учат делать.
А главное, как подается — «апогей возможностей». Я, простите, когда в школе в 8-9 классе учился, вокруг наблюдал куда большую культуру программирования.
Сейчас вот когда беру студентов 1-2 курса на парт-тайм — в массе своей тоже люди куда более адекватные, по-моему, попадаются. По крайней мере не пишут на C++ то, что на нем можно не писать, и вполне бойко ориентируются в каком-нибудь распространенном скриптовом языке (Python, PHP, Ruby, JS), не падают в обморок от известия о том, что в мире есть что-то кроме Windows, не смущаются проектов из больше, чем одного файла и т.д.
Nipheris
Классные к вам ребята приходят с первых-вторых курсов). С таким описанием (бойко ориентироваться хотя бы в одном скриптовом языке, не бояться факта существования *nix, не бояться проектов из >1 файла) к нам приходят выпускники, а не первокурсники. Это не лучшие, конечно, выпускники, но тем не менее десятки их. И возможно они даже толковые ребята в перспективе, просто испытывают полнейшие и абсолютное отсутствие практики.
GreyCat
Есть хорошие институты, где за 5-6 лет человеку что-то преподадут и он действительно будет достаточно загружен, чтобы развиваться именно тем и так, как ему предлагается в институте. Но их, разумеется, очень мало.
В массе своей в институтах преподают мало и плохо (в том числе фундаментальные вещи, которые по идее должны были бы), в итоге если человек из такого института 6 лет просиживал штаны, не развивался самостоятельно и не имеет практики — это уже индикатор. Человек не хочет развиваться, не имеет каких-то стремлений, и скорее эти 6 лет предпочитал играть в игрушки, пить пиво на лавочке или потратить их еще каким-нибудь подобным неконструктивным образом. Зачем брать на себя роль еще и воспитателя и пытаться это перевоспитать с неясной вероятностью успеха?
Nipheris
Нет, ну роль воспитателя брать на себя конечно ни к чему, я в принципе удивился возможности брать 1-2 курс на частичную занятость). У нас первые два курса был «букварь» — основы алгоритмов, основы языков программирования, к концу второго курса мы наконец узнали про списки, стеки и очереди. И я бы не сказал, что всё это реально уместить меньше чем на два курса.
Кстати, насчёт школы. Я тоже свою первую программу написал еще классе в 8 на QBasic-е, однако в моё время ориентироваться на школьную информатику было бы большой ошибкой. Об обучении программированию не могло быть и речи — информатика ограничивалась переводами чисел в разные системы счисления и оформлениями презентаций в ПаверПоинте. Надеюсь, ситуация изменилась с той поры (хотя, в Москве/Питере она наверное и так была неплохой, тут стандартная проблема «страны внутри страны»).
GreyCat
С моей точки зрения и из моего опыта — люди, которые ищут себе занятие и возможность получения практики и опыта с 1-2 курса — самые адекватные. Да, это не суперзвезды, но уже сам по себе факт того, что человек осознал, что нужно саморазвиваться — уже очень хороший шаг в нужном направлении.
Я занимался сам преподаванием — и в школе, и в институте — и со студентами, и с детьми. У меня дети подобные штуки делали где-то в районе 8-9 класса школы, с поправкой на то, что это, разумеется, был не C (и тем более не C++), и народ не стеснялся добавлять какие-то 3rd party библиотеки, чтобы иметь в своих играх графику. В 11 классе народ уже вовсю писал клиент-серверные сетевые игры.
Вот ниже человек отличные ссылки привел — https://habrahabr.ru/post/304448/#comment_9682844 — по-моему, хорошо иллюстрирует то, чем вполне человек может заниматься в 15 лет.
monah_tuk
Читаю, и создаётся впечатление другой планеты. Или рассы на этой. У нас в школе (90е) информатика была только в 10-11 классе. Выше писали про переводы систем счисления, ЛОГО, qbasic. Лично я знал это к тому времени, мне повезло, попала, лет в десять, книжка в руки — Лекции профессора Фортрана. А в 14 родители компьютер купили (за что им памятник — ведь у военных тогда с деньгами было туго. очень). Т.е. к окончанию школы я, более менее, освоился с бейсиком, паскалем (уровень turbo и delphi 3), Си и крошечку C++ (разные версии Borland C++ до 5.0 и C++Builder 4). А грузануть тогда можно было меня чем угодно: даже вопросом, что такое пузырьковая сортировка. Стек, очередь, прочие структуры данных и так далее — это вообще было за гранью...
Маленькая ремарка — интернета не было. Можно было купить модем и тратить по сотне рублей за час в самом дешёвом виде, но родителям бы я это объяснить не смог. Правда это не помешало в районе 9-10 класса обзавестись Linux второй системой :) Линуксоидов в нашем городке не было больше.
А у вас в 11 классе уже осилили клиент-серверную архитектуру...
GreyCat
Разница между тем, что я описываю и тем, что вы описываете, в двух вещах: в разнице поколений и в наличии наставник(а|ов), которые подталкивают молодой мозг в нужном направлении.
По большому счету, про себя лично я могу рассказать все примерно то же самое, что и вы, с поправкой на то, что компьютер у меня появился раньше, книжек было больше, в школе был доступ к MSX 2 с 6, кажется, класса и т.д. и т.п.
Освоить «клиент-серверную архитектуру» люди освоили, понятно, не сами, а им скромно помогали и подталкивали. Рассказали о том, что такое в целом есть, объяснили зачем и почему, показали какие-то примеры и т.д.
Keyten
Я просто оставлю это тут:
— Мои 15 лет: https://habrahabr.ru/post/138272/
— Мои 18 лет (в день, когда мне исполнилось 18, если точнее, отнять год-два на разработку): https://habrahabr.ru/post/239261/
ZEN_UA
Уважаемый, данная статья по моей задумке является выходом за зону типичных консольных задач, и никак не претендует на медаль. Я выложил ее в качестве псевдоразвлекательного материала для подобных мне по уровню изучающих С++. Если Вы дочитали статью, то заметили, что Unix — системы не были целевой платформой.
В любом случае спасибо за комментарий. Я ценю Ваш отклик и учту при написании следующей статьи.
pavel_pimenov
В коде есть delete [] temp;
drweb63
С учётом того, что человек пишет впервые и он первокурсник, то понятно что это похоже на курсовую. Но считаю что в черновики не стоит убирать. Если вы считаете, что для вас задача которую решил автор статьи тривиальна, то для других это может оказаться хорошим подспорьем для начала своего пути, да и просто для того чтобы вспомнить о старых играх и понастольгировать.
Antervis
человек, способный разобраться в этом коде, скорее всего будет в состоянии написать подобную игру с нуля.