Главная Другое
Экономика Финансы Маркетинг Астрономия География Туризм Биология История Информатика Культура Математика Физика Философия Химия Банк Право Военное дело Бухгалтерия Журналистика Спорт Психология Литература Музыка Медицина |
страница 1Санкт-Петербургский государственный политехнический университетФакультет технической кибернетики Кафедра компьютерных систем и программных технологий Курсовая работа по курсу «Программирование»Тема работы: «Разработка приложения с графическим интерфейсом на языке C++ с использованием библиотеки QT»Выполнила: Замотаева Юлия, гр. 1081/3 Преподаватель: доц. Пышкин Е.В. Санкт - Петербург 2012 1. Образ и границы проектаКурсовая работа посвящена разработке программного обеспечения для компьютерной игры «Змейка. Snake (Питон, Удав, Змейка и др.) – компьютерная игра, возникшая в середине или в конце 1970‐х. В свое время игра стала очень популярной как среди детей и молодежи, так и среди взрослого населения всего мира. В игре должны быть реализованы стандартные правила: В игре участвует один игрок, который управляет существом, напоминающим змею, которое ползает по плоскости (как правило, ограниченной стенками), собирая еду (или другие предметы), увеличивающие количество очков, но избегая столкновения с собственным хвостом и краями игрового поля. Каждый раз, когда змея съедает кусок пищи, она становится длиннее, что постепенно усложняет игру. Игрок управляет направлением движения головы змеи (обычно 4 направления: вверх, вниз, влево, вправо), а хвост змеи движется следом. Игрок не может остановить движение змеи. Поле при этом разбито на некоторое количество квадратов. Каждый из таких квадратов является отдельной частью поля, которая может быть либо стеной, либо обычным полем по которому можно ползать, либо едой. Игра должна иметь счетчик набранных игроком очков, таблицу игроков, которая формируется в файле после окончания игры. ![]() 2. Техническое заданиеРазработать данное приложение, представленное в предыдущем пункте на языке C++ с использованием библиотеки Qt для реализации графического интерфейса пользователя. Режимы работы приложенияРеализуется два режима работы этапа:
Требования к консольному интерфейсуГлавное меню консольного приложения: 1) Выбрать сценарий. 2) Описание игры (сценариев). 3) Выйти из игры. Основные сценарии функционирования программыОсновной сценарий функционирования консольного приложения состоит в следующем:
Требования к функциональности консольного приложения
Требования к графическому пользовательскому интерфейсу
Основной сценарий функционирования программыОсновной сценарий функционирования приложения состоит в следующем:
Регистрация игрока: игрок должен ввести имя (ник), под которым он будет играть (ведение записи очков).
Формирование результатов: подсчет съеденных груш и яблок и перевод их в очки (1 яблоко- 10 очков, 1 груша-20), а также время игры. После окончания игры набранное число очков данным игроком сохраняется вместе с его именем в текстовый выходной файл. С последующим сохранением очков и имени следующего игрока, текстовый файл сортируется по возрастанию очков.
Форматы данныхВ текстовом файле содержатся имена игроков с их результатами. Он обновляется (редактируется) после окончания игры и загружается при выборе необходимой кнопки меню. Обработка ошибокПриложение должно обрабатывать следующие виды ошибок: Консоль:
Графика: 1) Вывести сообщение об ошибке, если игрок попытался остановить змею (нажал противоположную движению клавишу) – в том случае, если получится удовлетворительно поработать с динамикой и змея будет двигаться без остановок. 2) Ошибка загрузки входного файла с очками игроков. 3. Проектирование системной архитектурыКлассы консольного приложенияВ консольном приложении будут реализованы следующие классы:
private: int** field; int width, height; public:
Field (int W, int H); Field (); ~Field (); bool set_field (int x, int y, int new_value); //для изменения ячейки поля int get_field (int x, int y); //получить ячейку int get_width (); bool set_width (int new_width); int get_height(); bool set_height (int new_height); bool createField (); void init (); bool resize(int size1, int size2); }; Класс Field отвечает за представление игрового поля. На данном этапе возвращает конкретные символы, определенные нахождением тех или иных объектов на нем.
private: int x, y; public: Fruct (int X, int Y); ~Fruct(); int getx(); int gety(); bool setx (int new_x); bool sety (int new_y); virtual int fructenumerate ( )=0; }; Класс Fruct отвечает за представление единичного фрукта, является абстрактным базовым классом. От него наследуются следующие классы: Яблоко, Груша.
public: Apple (int X, int Y); ~Apple(); int fructenumerate (); };
public: int time; Pear (int t, int X, int Y); ~Pear();
int fructenumerate (); };
private: int numberfructs; //число фруктов public: std::vector Fructs (int len); Fructs(); bool set_numberfructs (int new_numberfructs); int get_numberfructs (); void add (int size1,int size2); //случайное добавление фруктов void addApple(Apple *new_apple);//вручную добавляем void addPear(Pear *new_pear); bool deleteFruct(int number); }; Класс Fructs отвечает за представления фруктов(мн.ч). Включает в себя динамический массив и различные методы.
private: int time; int cycle_snake; float score; public: Game ();
~Game(); Scenario1 *scenario1; Scenario2 *scenario2; Scenario3 *scenario3; Scenario *scenario0; int gettime(); bool settime(int newtime); int getcycle_snake(); bool setcycle_snake(int newcycle_snake); void update(); void printField(Scenario*currentscenario); void updateField(Scenario*currentscenario); static char intToChar (int code); //служебная функция для норм.отрисовки поля static void printToFile(int cycle,Scenario*currentscenario); }; Класс Game отвечает за сам игровой процесс. (В консоли это предполагает запуск набора сценариев).
{ public:
Field *scenarioField; Zmeika *scenarioZmeika; Fructs *scenarioFructs; Scenario(void); ~Scenario(void); void virtual init ()=0; bool virtual run(int cycle_snake)=0;
Класс Scenario обеспечивает наличие разных сценариев. Базовый класс, от которого наследуются следующие сценарные классы:
{ public: Scenario1(void); ~Scenario1(void); void init (); bool run(int cycle_snake); };
{ public:
Scenario2(void); ~Scenario2(void); void init (); bool run(int cycle_snake); };
{ public:
Scenario3(void); ~Scenario3(void); void init (); bool run(int cycle_snake); };
private: int headx, heady; int napx, napy; bool alive; int dir; public:
Zmeika(); Zmeika(int X, int Y, int Napx, int Napy, int LTail); Zmeika(int X, int Y, int new_direction, int LTail); ~Zmeika(); bool getAlive(); void setAlive(bool newalive); bool setdir(int newdir); int getdir(); int get_headx(); int get_heady(); bool set_headx (int new_x); bool set_heady (int new_y); int get_napx(); int get_napy(); bool set_napx (int new_napx); bool set_napy (int new_napy); std::vector ZmElement* getElementTail2(int Number); int enumerateHead (); int enumerateTail (); bool rotateUp(); bool rotateDown(); bool rotateLeft(); bool rotateRight(); bool rotateClockwise(); //по часовой стрелке bool rotateAClockwise(); //против bool move(); void shift(); bool checkEatFruct(Fructs *allFructs,Field *fullfield); bool checkWall(Field *fullfield); bool checkPosition(int X,int Y); bool checkSelfEating(); bool addTail(Field *fullfield); } Класс отвечает за представление всей змейки в целом.
private: int x, y; int napx, napy; int dir;
public: ZmElement (); ZmElement (int X, int Y); ~ZmElement(); int getx(); int gety(); bool setx (int new_x); bool sety (int new_y); int getnapx(); int getnapy(); bool set_napx(int new_napx ); bool set_napy(int new_napy); }; Класс отвечает за представление элементов, из которых состоит змея (то есть, не включая головы).
bool fructsCreator (Fructs*fruits) ; //создан ли, ск элементов bool zmeikaCreator (Zmeika*zmeia) ; // змейка, хвост bool fieldCreator (Field*field) ;//поле }; Тестовый класс (создавался для отладки приложения).
{ public:
HighScores(); virtual ~HighScores(); std::vector std::vector bool addNewScore(char * new_name,int score); bool saveToFile(); bool loadFromFile();
Класс для ведения учетной записи игрока. Понадобится для графического интерфейса. Процесс тестирования приложения:
![]() Выбираем 1 пункт меню: ![]() И снова 1: ![]() ![]() Видим, что змея съела фрукт, и произошло увеличение длины хвоста, программа работает верно. Остальные сценарии также были запущены, и все работало исправно. Также проводились изменения в сценариях, например, в первом в самом коде создавалось поле другого размера, выводилось не яблоко, а груша (в принципе в данной версии консоли принципиально они не отличаются), у змеи были другие координаты, и все также работало верно. Классы графического интерфейсаК вышеперечисленным классам добавляются: class AboutDialog: public QDialog { Q_OBJECT
QLabel *label; protected: virtual void paintEvent(QPaintEvent *); public:
AboutDialog(QWidget *parent); ~AboutDialog(); }; Данный класс отвечает за вывод окна с описанием приложения. class FinalResults : public QDialog { Q_OBJECT public: FinalResults(int newscore,QWidget *parent); protected: virtual void paintEvent(QPaintEvent *); QLineEdit *Editname; QPushButton *ButtonCommit; public slots: void oncommitname(); public: bool SaveToFile(); int score; }; class ScoreDialog : public QDialog { Q_OBJECT
protected: virtual void paintEvent(QPaintEvent *); public: bool LoadFromFile(); ScoreDialog(QWidget *parent); ~ScoreDialog(); HighScores Records; QLabel *text; vector }; Данные классы отвечают за представление результатов игры отдельном окне. class Game : public QMainWindow { Q_OBJECT public: Field * Gfield; Zmeika *Gzmeika; Fructs *Gfructs; public: virtual void keyPressEvent(QKeyEvent * ev); void paintEvent(QPaintEvent*); void update(); void initgame(); void addfructs(int amount); void updatefield(); bool checkPositionForFruct(int X,int Y); private: bool Pause; public: Game();
~Game() {} }; Класс отвечает за представление игры в целом. class MyDialog: public QDialog { Q_OBJECT protected: virtual void paintEvent(QPaintEvent *); virtual void keyPressEvent(QKeyEvent * ev); public:
MyDialog(QWidget *parent); ~MyDialog(); Game * newGame; bool state1; bool state2; }; Класс отвечает за представление игры в отдельном окне. class Widget : public QWidget { Q_OBJECT QPushButton* button1; QPushButton* button2; QPushButton* button3; QPushButton* button4; public: MyDialog* Gdialog; ScoreDialog* Sdialog; AboutDialog* Abdialog; public: Widget(QWidget *parent = 0); ~Widget(); Данный класс отвечает за создание меню приложения. Процесс тестирования приложения:
![]()
![]()
![]()
![]()
Видим, что процесс теста прошел достаточно удачно. Однако, при проведении многих тестов обнаружились следующие недостатки: управление с помощью клавиш немного виснет (не успевает за змейкой), также при съедании змейкой много фруктов, хвост наращивается немного не так, как нужно. Это будет обязательно доработано и исправлено в дальнейшем. В целом, считаю, что задача о создании игры «Змейка» мною выполнена. Летняя практикаВ рамках летней практики мной были произведены следующие изменения курсовой работы, выполненной во 2 семестре:
2. Появление музыкального сопровождения приложения; 3. Добавлены возможности сохранения загрузки сохраненной игры; 4. Включение в игру возможность паузы. Теперь при запуске приложения пользователь видит необычное красочное меню с яркими кнопками: ![]()
Улучшена начальная страница приложения – заливка заднего фона, выделение цветом кнопок, изменения положения кнопок(About и Exit) для удобства их использования, увеличено и более интересно раскрашено игровое поле, окраска змеи стала более яркая: void Widget::paintEvent(QPaintEvent *) { setWindowTitle("Snake"); QPainter painter(this); QLinearGradient gradient (0,0,width(),height()); gradient.setColorAt(0,Qt::red); gradient.setColorAt(0.5,Qt::green); gradient.setColorAt(1,Qt::blue); painter.setBrush(gradient); painter.drawRect(rect()); QVBoxLayout* layout = new QVBoxLayout(); button1 = new QPushButton("Game"); button1->setStyleSheet("background-color: rgb(200, 255, 100);"); button2 = new QPushButton("Show score"); button2->setStyleSheet("background-color: rgb(200, 255, 100);"); button3 = new QPushButton("Exit"); button3->setStyleSheet("background-color: rgb(200, 255, 100);"); button4 = new QPushButton("About"); button4->setStyleSheet("background-color: rgb(200, 255, 100);");
Теперь с начала запуска приложения включается музыка и одна и та же песня играет несколько раз: int main(int argc, char *argv[]) { QApplication a(argc, argv); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("Windows-1251")); Widget w; w.show(); Phonon::MediaObject media; Phonon::AudioOutput ao(Phonon::MusicCategory); Phonon::createPath (&media, &ao); // QObject::connect(&media, SIGNAL(finished()), &app, SLOT(quit())); media.setCurrentSource(Phonon::MediaSource(":/coca")); media.enqueue(Phonon::MediaSource(":/coca")); media.enqueue(Phonon::MediaSource(":/coca")); media.play(); return a.exec(); }
Сохранение игры происходит в текстовый файл Game.txt, в котором в столбик выводятся все необходимые данные (координаты змеи, длина хвоста и т.д ): bool Game::SaveToFile() { FILE * SaveFile=fopen("Game.txt","w+"); if(SaveFile) { //список всех записываемых переменных int Rwidth=this->Gfield->get_width(); int Rheight=this->Gfield->get_height(); int RLtail=this->Gzmeika->Tail2.size(); //длина хвоста int RNfru=this->Gfructs->Fruits.size(); //число фруктов int RX=0; //х-координата объекта int RY=0; //y-координата объекта int Dirx=0; //направление по x int Diry=0; //направление по y int Type=1; //Тип фрукта //int Time=0; //время игры или фрукта //string Name //имя игрока float score=this->MathPoints();//счет игры fprintf(SaveFile,"width%d\nheigth%d\n",Rwidth,Rheight); fprintf(SaveFile,"Tail%d\nFructs%d\n",RLtail,RNfru); RX=this->Gzmeika->get_headx(); RY=this->Gzmeika->get_heady(); Dirx=this->Gzmeika->get_napx(); Diry=this->Gzmeika->get_napy(); fprintf(SaveFile,"Head%d\t%d\t%d\t%d\n",RX,RY,Dirx,Diry); for (int i=0;i {
RX=this->Gzmeika->Tail2[i]->getx(); Dirx=this->Gzmeika->Tail2[i]->getnapx(); Diry=this->Gzmeika->Tail2[i]->getnapy(); fprintf(SaveFile,"Tail#%d\t%d\t%d\t%d\t%d\n",i,RX,RY,Dirx,Diry); } for (int ii=0;ii RX=this->Gfructs->Fruits[ii]->getx(); RY=this->Gfructs->Fruits[ii]->gety(); Type=this->Gfructs->Fruits[ii]->gettype(); fprintf(SaveFile,"Fruct#%d\t%d\t%d\t%d\n",ii,RX,RY,Type); } fprintf(SaveFile,"Score %d\n",score); fclose(SaveFile); return true; } fclose(SaveFile); return false; } Загрузка сохраненной игры происходит таким же образом: открывается текстовый файл Game.txt, откуда считывается информация, после чего поле заполняется строго определенным образом bool Game::LoadGame() { FILE * OpenFile=fopen("Game.txt","r"); if(OpenFile) { //список считываемых данных int Rwidth=0; int Rheight=0; int RLtail=0; //длина хвоста int RNfru=0; //число фруктов int RX=0; //х-координата объекта int RY=0; //y-координата объекта int Dirx=0; //направление по x int Diry=0; //направление по y int Num=0; int Type=1; //Тип фрукта //int Time=0; //время игры или фрукта //string Name //имя игрока float score=0; //счет игры fscanf(OpenFile,"width%d\nheigth%d\n",&Rwidth,&Rheight); fscanf(OpenFile,"Tail%d\nFructs%d\n",&RLtail,&RNfru); fscanf(OpenFile,"Head%d\t%d\t%d\t%d\n",&RX,&RY,&Dirx,&Diry); this->Gzmeika->set_headx(RX); this->Gzmeika->set_heady(RY); this->Gzmeika->set_napx(Dirx); this->Gzmeika->set_napy(Diry); for(int j=0;j {
fscanf(OpenFile,"Tail#%d\t%d\t%d\t%d\t%d\n",&Num,&RX,&RY,&Dirx,&Diry); this->Gzmeika->Tail2[Num]->sety(RY); this->Gzmeika->Tail2[Num]->set_napx(Dirx); this->Gzmeika->Tail2[Num]->set_napy(Diry); } for (int ii=0;ii fscanf(OpenFile,"Fruct#%d\t%d\t%d\t%d\n",&Num,&RX,&RY,&Type); this->Gfructs->Fruits[Num]->setx(RX); this->Gfructs->Fruits[Num]->sety(RY); this->Gfructs->Fruits[Num]->settype(Type); } //WriteFructsStatusToFile(game->Gfructs); //WriteTailStatusToFile(game->Gzmeika); fclose(OpenFile); return true; } fclose(OpenFile); return false; } Управление: кнопки 1 и 2.
bool Game::GetPause() { return this->Pause; } void Game::SetPause(bool NPause) { this->Pause=NPause; } void MyDialog::keyPressEvent(QKeyEvent *ev) { switch (ev->key()) { //LEFT
case 16777234: this->newGame->Gzmeika->rotateAClockwise(); break; //RIGHT
case Qt::Key_Right://16777236: this->newGame->Gzmeika->rotateClockwise(); break; case Qt::Key_1: this->newGame->SaveToFile(); break;
case Qt::Key_2: this->newGame->SetPause(true); this->newGame->LoadGame(); this->newGame->SetPause(false); break; case Qt::Key_0: this->newGame->SetPause(true); break;
case Qt::Key_9: this->newGame->SetPause(false); break; }
Управление: кнопки 1 и 9. Смотрите также: Курсовая работа по курсу «Программирование» Тема работы: «Разработка приложения с графическим интерфейсом на языке C++ с использованием библиотеки qt»
301.1kb.
1 стр.
Курсовая работа по курсу «Программирование» Тема работы: «Разработка приложения с графическим интерфейсом на языке программирования С++ с использованием библиотеки qt»
108.12kb.
1 стр.
Курсовая работа 230201 Информационные системы и технологии на предприятиях
146.74kb.
1 стр.
Курсовая работа По курсу " организация процессов данных и приложений "
211.2kb.
1 стр.
Лабораторная работа Использование стандартных компонентов в C++ Builder
87.05kb.
1 стр.
Годовой план работы библиотеки мбоу «Суксинская сош» на 2012-2013 учебный год Тема работы библиотеки Роль библиотеки в повышении конкурентоспособности системы образования Задачи библиотеки
187.84kb.
1 стр.
Курсовая работа на тему
473.95kb.
1 стр.
Курсовая работа «Проектирование вычислительной системы»
320kb.
1 стр.
Курсовая работа цели курсовой работы
110.1kb.
1 стр.
Курсовая работа является обязательным видом итогового контроля по курсу «Технологические основы социально-культурной деятельности»
721.72kb.
3 стр.
Курсовая разработка по курсу «Теория литературы»
1048.27kb.
6 стр.
Урок информатики в 7 классе «Векторные графические редакторы» 114.59kb.
1 стр.
|