Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: Программирование на C / C++


Хостинг Портала RusFAQ.ru:
MosHoster.ru - Профессиональный хостинг на Windows 2008

РАССЫЛКИ ПОРТАЛА RUSFAQ.RU

Чемпионы рейтинга экспертов в этой рассылке

Micren
Статус: Практикант
Рейтинг: 101
∙ повысить рейтинг >>
Hubbitus
Статус: 10-й класс
Рейтинг: 98
∙ повысить рейтинг >>
witek25
Статус: 3-й класс
Рейтинг: 40
∙ повысить рейтинг >>

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / C/C++

Выпуск № 1291
от 22.04.2009, 23:05

Администратор:Dr_Andrew

Нам важно Ваше мнение об этой рассылке.
Оценить этот выпуск рассылки >>




Данная статья является продолжением статьи Работа в QDevelop



Кроссплатформенные "Пятнашки" в QDevelop.


Этап 0. Создание
заготовки приложения


А для чего это всё?


Интегрированная среда разработки
Qt-приложений, QDevelop, ориентирована на создание и редактирование
проектов с включением ui-форм, т.е. xml-заготовок будущих окон
приложения с возможностью их редактирования в Qt Designer по технологии
WYSIWYG (что видишь, то и получишь). Подобная технология весьма
популярна, поскольку позволяет быстро разрабатывать программу,
занимаясь лишь логикой её работы и не отвлекаясь на тонкости
программирования пользовательского интерфейса.


Однако нередко возникает ситуация,
когда удобнее программировать главное окно приложения по-старинке,
средствами C++ классов Qt, например, при динамическом изменении
внешнего вида формы. Хотя QDevelop лишён средств по созданию подобных
проектов, однако данная среда обладает инструментами, которые позволят
сделать разработку данного типа проекта более удобным и приятным.


В качестве примера работы с написанным
вручную проектом мы рассмотрим создание электронной версии классической
головоломки "Пятнашки" (Fifteen-puzzle game), которая традиционно
является учебным примером для начинающих программистов. 


Сама мысль написать "Пятнашки" для
Linux возникла у меня давным-давно, ещё во времена версии 4.1
библиотеки Qt в связи с вопросом 130703
и вопросом
83102
рассылки по C/C++ RusFAQ. Предварительно программа была
написана с использованием Qt 3.3.8, а затем портирована на Qt 4.2 с
некоторым расширением функциональности (был добавлен режим работы
"Собери картинку"). При работе над программой  я обратил
внимание, что мною были так или иначе затронуты если не все, то
основные возможности, заложенные в Qt, поэтому созданная
программа Klikit
является хорошим учебным примером, по освоению работы с этой
библиотекой. Собственно, именно поэтому и была написана эта статья.


В настоящее время созданы определённые
нормы поэтапной разработки приложений для Linux, которых мы и будем
придерживаться.


Формулировка цели и задач проекта


Целью проекта является разработка и
внедрение компьютерной реализации настольной игры "Пятнашки".


Задачами проекта являются:



  • Создание кроссплатформенного приложения (как минимум для
    Linux и Windows);

  • Возможность переключения между двумя режимами: классическим
    (фишки с номерами) и "собери картинку";

  • Предусмотреть в программе настраиваемый интерфейс с
    возможностью сохранения и загрузки настроек;

  • Расширяемая локализация приложения с возможностью
    добавления новых языков интерфейса без необходимости повторной
    компиляции исполняемого модуля.


Поиск научно-патентной информации для установления степени
разработки вопроса сторонними авторами


Приняв решение написать игру,
заинтересовался: а много ли написано на C++ кроссплатформенных
"Пятнашек"? Ориентируясь на количество исходников для MS DOS и MS
Windows, ожидал обвала, но с удивлением обнаружил, что даже для
исключительно Linux "Пятнашек" раз-два и обчёлся: имеется пара древних
проектов с
псевдографическим интерфейсом, плюс Jesper Thomschütz aka Jespersaur
добавил в плазмоиды KDE 4 свою версию головоломки.


Критика аналогов


Из кроссплатформенных компьютерных
реализаций головоломки я обнаружил лишь один проект на Python с
интерфейсом на Tcl/Tk, что выглядит несовременно....


Критика прототипа


В качестве прототипа "Пятнашек" я
выбрал плазмоид KDE 4 Jesper Thomschütz aka Jespersaur. Хотя, строго
говоря, проект не является кроссплатформенным, но его легко сделать
таковым, поскольку в качестве библиотеки разработки пользовательского
интерфейса была выбрана библиотека Qt 4.x. Однако изучение работы
программы показало её низкую функциональность: слабо настраиваемый
интерфейс и недостаточно проработанные механизмы взаимодействия с
пользователем, в частности, отсутствие проверки на выигрыш (при решении
головоломки программа никак на это не реагирует). На рисунке ниже
представлен вышеупомянутый плазмоид (слева) и моё видение программы
(справа):


Изображение 578336 - savepic.ru


Выбор языка и средств разработки проекта


В соответствии с задачами проекта
программу напишем на языке C++. Для проектирования пользовательского
интерфейса будем использовать версию библиотеки Qt 4.2 для
достижения целей совместимости со старыми версиями дистрибутивов Linux
(тем не менее, код полностью совместим со старшими версиями библиотеки).
В качестве IDE используем QDevelop, как среду разработки,
ориентированную на работу с Qt.


Проектирование основного интерфейса программы


Создание проекта


Создайте в каталоге Ваших проектов
папку Klikit. В этой папке создайте текстовый файл main.cpp. Откройте
файл в любом текстовом редакторе и наберите следующий текст:



#include "TMainForm.h"

//--------------------------------------------------------------

#include <QApplication>

//--------------------------------------------------------------

int main(int iArgc, char* psArgv[])

{

  QApplication MyProgramme(iArgc, psArgv); // Создаём
экземпляр класса
приложения

  TMainForm MainWindow; // Создаём экземпляр класса
главного окна

  MainWindow.show(); // Показываем главное окно

  return MyProgramme.exec(); // Запускаем главный
цикл прложения

}

Несмотря на то, что подключаемый
заголовочный файл TMainForm.h ещё не существует, мы уже можем создать
проект. Для этого воспользуемся утилитой qmake, входящей в состав
библиотеки Qt. Перейдём в консоли в папку программы (Klikit) и наберём:
qmake -project


N.B.!
Если Вы пользователь так называемого dual-qt дистрибутива
Linux (т.е. такого, в котором имеются как 3-я, так и 4-я версии
библиотеки), то набирайте команду qmake с указанием полного пути к
ней: 


Изображение 547657 - savepic.ru


Тем самым в папке программы будет
создан проект Qt, файл с расширением имени *.pro - Klikit.pro. Иногда
его называют
платформо-независимым файлом проекта. В принципе на его основе можно
создать платформо-зависимый файл проекта (Makefile) - набор инструкций
конкретному компилятору по сборке исполняемого файла. Для этого
достаточно набрать в консоли qmake Klikit.pro. Но вручную это мы
делать не будем, поскольку в QDevelop этот процесс автоматизирован.


Добавление в проект нового класса


Откройте созданный файл проекта в
QDevelop, выбрав в меню Проект -
Открыть проект... Теперь нам предстоит создать класс главной формы
приложения. Дабы упростить процесс создания и включения в проект
необходимых файлов, а также для, того, чтобы сгенерировать часть кода,
выберите в меню QDevelop Проект - Добавить новый класс... 


В появившемся диалоговом окне "Добавить
новый класс" в поле "Имя класса" внесите TMainForm; в поле "Параметры
конструктора" - QWidget* pParent, Qt::WindowFlags Flag; в поля
"Родительский класс" и "Имя файла родительского класса" внесите
QMainWindow; в выпадающем списке "Тип наследования" выберите public;
отметьте флажковый переключатель "Наследование другого класса"; в
поле "Имя файла заголовка" внесите TMainForm.h, а в поле "Имя файла
реализации" - TMainForm.cpp.  Нажмите OK:


Изображение 576328 - savepic.ru


На вкладке "Файлы" окна "Состав
проекта" QDevelop
раскройте древовидные списки "Исходники" и "Заголовки". Дважды щёлкните
по названиям файлов объявления и реализации, чтобы открыть их в
редакторе QDevelop. Присвойте параметру конструктора TMainForm pParent
значение 0, а параметру Flag значение Qt::Window:


TMainForm(QWidget* pParent = 0, Qt::WindowFlags Flag =
Qt::Window);

Не забудьте добавить параметры в
конструктор QMainWindow в файле реализации класса TMainForm:



TMainForm::TMainForm(QWidget* pParent, Qt::WindowFlags Flag)

  : QMainWindow(pParent, Flag)

Добавление в класс нового метода


Перейдите на вкладку "Классы" окна
"Состав проекта" QDevelop. В древовидном списке проекта (Klikit.pro)
щёлкните правой кнопкой мыши по названию класса
(TMainForm) и в контекстном меню выберите "Добавить Метод...":


Изображение 558943 - savepic.ru


В открывшемся диалоговом окне "Добавить
новый метод в класс" в поле "Имя Метода" введите LanguageChangeSlot; в
выпадающем списке "Возвращаемый тип" оставьте значение void; а в
выпадающем списке "Тип наследования" выберите public slots. Нажмите OK,
чтобы сгенерировать заготовки кода объявления и реализации метода
(слота) класса. 


Изображение 559955 - savepic.ru


Данный слот в будущем будет отвечать за
интернационализацию (перевод строк интерфейса) нашей программы.
Поскольку мы будем вызывать слот в различных местах программы, мы
объявили его открытым (public). Добавим в наш слот функциональности.
Перейдите к заготовке реализации слота и наберите в ней this->.
В появившемся окне автодополнения кода наберите setW, после чего
выберите setWindowTitle и нажмите ENTER. Внутри функции
this->setWindowTitle(); наберите tr("Klikit - 15-puzzle").


Функция setWindowTitle отвечает за
отображение заголовка окна. В том случае, если она не была вызвана, в
заголовке окна отображается название приложения. Все строки программы,
которые мы в будущем намерены переводить, необходимо "обрамлять"
функцией tr - именно она сообщает переводчику о необходимости замены
строки интерфейса программы на переведённую строку.


Разумеется, мы могли бы просто набрать
setWindowTitle(tr("Klikit - 15-puzzle")); вручную, не обращаясь к this,
но автодополнение кода сильно ускоряет работу.


Для того, чтобы метод вызывался во
время работы программы, добавим его в конструктор класса TMainForm.


Задание размеров формы


Как правило, если геометрия виджета не
была задана явно, то он отображается в минимально допустимом размере,
определяемом обычно его (виджета) содержимым. Поскольку главное окно
нашего приложения пустое, оно будет выглядеть не слишком красиво.


Зададим его размеры явно с помощью
функции resize. Наберите в конструкторе класса TMainForm



resize(344, 344);

В качестве параметров функция принимает
целые числа (ширина и высота виджета). Поскольку в нашем примере эти
характеристики главного окна приложения будут определяться размером
игрового поля с набором фишек, то в будущем мы эту функцию уберём из
конструктора.


Отредактируйте исходные тексты класса
TMainForm, чтобы они выглядели так:


// Файл TMainForm.h

#ifndef _TMainForm_h_

#define _TMainForm_h_

//----------------------------------------------------------

#include <QMainWindow>

//----------------------------------------------------------

class TMainForm : public QMainWindow

{

  Q_OBJECT



public:

  
TMainForm(QWidget* pParent = 0, Qt::WindowFlags Flag = Qt::Window);

  ~TMainForm();



public slots:

  void LanguageChangeSlot();

};

//----------------------------------------------------------

#endif



// Файл TMainForm.cpp

#include "TMainForm.h"

//----------------------------------------------------------

TMainForm::TDialogForm(QWidget* pParent, Qt::WindowFlags Flag)

  : QMainWindow(pParent, Flag)

{

  LanguageChangeSlot();

  resize(344, 344);

}

//----------------------------------------------------------

TMainForm::~TMainForm()

{

}

//----------------------------------------------------------

void TMainForm::LanguageChangeSlot()

{

  
this->setWindowTitle(tr("Klikit - 15-puzzle"));

}

//----------------------------------------------------------


Откомпилируйте программу и запустите её
на выполнение (F7 - F5). Убедитесь, что происходит показ главного окна
приложения с заданными размерами и заголовком. 


К слову, данный код является неплохой
заготовкой для создания будущих приложений, так что рекомендую
сохранить нашу заготовку на будущее.


На следующем этапе нам предстоит работа
с файлом ресурсов и создание заготовок меню, а также панелей
инструментов и состояния будущей программы.


Удачи!


Администратор: Dr_Andrew


Вопрос № 165157: Уважаемые эксперты,помогите -будьте так добры Дана матрица D[N,M]. Найти в каждой строке матрицы максимальный и минимальный элементы и поменять их местами с первым и последним элементом строки соответственно....
Вопрос № 165160: Здравствуйте, уважаемые эксперты. Прошу вашей помощи в решении задачи!! <u><i>Тема:</i></u> <u>Строки</u> <u><i>Задача:</i></u> Ввести текст на русском языке. Преобразовать его таким образом, чтобы в каждом слове слоги шли в обратном порядке...
Вопрос № 165168: Доброго времени суток, уважаемые эксперты. Просьба помочь в следующей задаче: Даны натуральные числа K и N. Составить программу формирования массива А, элементами которого являются числа, сумма цифр которых равна К и которые не больше N. З...

Вопрос № 165.157
Уважаемые эксперты,помогите -будьте так добры
Дана матрица D[N,M]. Найти в каждой строке матрицы максимальный и минимальный элементы и поменять их местами с первым и последним элементом строки соответственно.
Отправлен: 16.04.2009, 22:59
Вопрос задал: Redman (статус: Посетитель)
Всего ответов: 1
Мини-форум вопроса >>> (сообщений: 6)

Отвечает: Micren
Здравствуйте, Redman!
Программа:
Код:

#include <locale>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <limits>

using namespace std;

int main()
{
locale::global(locale("russian_russia.866"));
// Размерности матрицы
const unsigned int N=8,M=5;
// Матрица
int array[N][M];
srand(static_cast<unsigned int>(time(0)));
// Заполним матрицу случайными значениями и выведем ее
wcout<<L"Исходный массив:"<<endl;
for(unsigned int i=0;i<N;++i)
{
for(unsigned int j=0;j<M;++j)
{
array[i][j]=static_cast<int>(static_cast<double>(rand())/RAND_MAX*50);
wcout<<setw(3)<<array[i][j]<<L' ';
}
wcout<<endl;
}
// Пройдем по кажной строке
for(unsigned int i=0;i<N;++i)
{
// Индексы минимального и максимального элемента в строке
int minIndex=0,maxIndex=0;
for(unsigned int j=1;j<M;++j)
{
minIndex=array[i][j]<array[i][minIndex]?j:minIndex;
maxIndex=array[i][j]>array[i][maxIndex]?j:maxIndex;
}
// Поменяем местами согласно условию
swap(array[i][0],array[i][maxIndex]);
if(minIndex==0)minIndex=maxIndex;
swap(array[i][M-1],array[i][minIndex]);
}
// Выведем результат
wcout<<L"Результирующий массив:"<<endl;
for(unsigned int i=0;i<N;++i)
{
for(unsigned int j=0;j<M;++j)
{
wcout<<setw(3)<<array[i][j]<<L' ';
}
wcout<<endl;
}
system("PAUSE");
return 0;
}

Тестировалась в M S VS 2008.
Пример работы:
Код:

Исходный массив:
4 33 15 24 20
40 5 43 17 49
7 5 24 15 18
43 37 23 26 3
15 24 20 18 45
45 44 45 44 24
24 1 0 9 17
28 5 11 47 12
Результирующий массив:
33 20 15 24 4
49 40 43 17 5
24 18 7 15 5
43 37 23 26 3
45 24 20 18 15
45 44 45 44 24
24 1 17 9 0
47 12 11 28 5
Ответ отправил: Micren (статус: Практикант)
Ответ отправлен: 17.04.2009, 06:53

Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 247676 на номер 1151 (Россия) | Еще номера >>
  • Отправить WebMoney:
  • Вам помогли? Пожалуйста, поблагодарите эксперта за это!

    Оценка за ответ: 4


    Вопрос № 165.160
    Здравствуйте, уважаемые эксперты. Прошу вашей помощи в решении задачи!!
    Тема: Строки
    Задача:
    Ввести текст на русском языке. Преобразовать его таким образом, чтобы в каждом слове слоги шли в обратном порядке. Например: "мама мыла раму" -> "мама ламы мура".
    Если можно с объяснениями.
    Заранее спасибо.
    Отправлен: 16.04.2009, 23:29
    Вопрос задал: Terqu
    Всего ответов: 1
    Мини-форум вопроса >>> (сообщений: 2)

    Отвечает: Ilkras
    Здравствуйте, Terqu!
    Решение такое:
    Код:

    /*
    Ввести текст на русском языке.
    Преобразовать его таким образом,
    чтобы в каждом слове слоги шли в обратном порядке.
    Например: "мама мыла раму" -> "мама ламы мура".
    */


    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    #include <string.h>


    void main(void)
    {
    char in_str[512];
    char out_str[512];
    int i, j, k, l;
    size_t len;

    gets(in_str);//ввести текст
    memset(out_str, 0, 512);//инициализируем строку символами конца строки

    len = strlen(in_str);

    i=l=0;
    while(isspace(in_str[i]))// убрать пробелы слева
    i++;

    while(i < len)
    {
    for(k=i; isalpha( in_str[k]);k++);//ищем конец слова

    for(j=k-1; j>=i; j--)
    out_str[l++] = in_str[j]; // перевернем слово
    out_str[l++] = ' ';//добавим пробел

    i = k;

    while(!isalpha(in_str[i])&& i < len)//ищем следующую букву - начало слова
    i++;
    }
    printf("You typed: %s ", in_str);
    printf("I type: %s ", out_str);

    }


    Вводим:
    The quick brown fox jumps over the lazy dog
    Получаем:
    You typed: The quick brown fox jumps over the lazy dog
    I type: ehT kciuq nworb xof spmuj revo eht yzal god
    Ответ отправил: Ilkras (статус: Студент)
    Ответ отправлен: 20.04.2009, 02:07

    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 247864 на номер 1151 (Россия) | Еще номера >>
  • Отправить WebMoney:
  • Вам помогли? Пожалуйста, поблагодарите эксперта за это!

    Оценка за ответ: 5


    Вопрос № 165.168
    Доброго времени суток, уважаемые эксперты. Просьба помочь в следующей задаче:
    Даны натуральные числа K и N. Составить программу формирования массива А, элементами которого являются числа, сумма цифр которых равна К и которые не больше N.

    Заранее благодарю.
    Отправлен: 17.04.2009, 00:50
    Вопрос задал: Falc0n (статус: 2-й класс)
    Всего ответов: 2
    Мини-форум вопроса >>> (сообщений: 0)

    Отвечает: Ilkras
    Здравствуйте, Falc0n!
    решение вашей задачи ниже. Если есть вопросы - пишите в форуме.

    Приложение:

    Ответ отправил: Ilkras (статус: Студент)
    Ответ отправлен: 17.04.2009, 02:51

    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 247672 на номер 1151 (Россия) | Еще номера >>
  • Отправить WebMoney:
  • Вам помогли? Пожалуйста, поблагодарите эксперта за это!

    Оценка за ответ: 5
    Комментарий оценки:
    Большое спасибо


    Отвечает: Терсков Сергей
    Здравствуйте, Falc0n!
    Вот вариант с использованием класса STL - vector. Функция int digit_summ(int number) считает сумму цифр в переменной number.
    Код:

    #include <vector>
    #include <iostream>

    using namespace std;

    int digit_summ(int number) {

    int result = 0;

    while(number != 0) {

    result += number%10;
    number /= 10;
    }

    return result;
    }

    int main(int argc, char *argv[]) {

    int N = 500;
    int K = 10;

    vector<int> A;

    cout << "N = " << N << endl << "K = " << K << endl << endl;

    for(int i=0; i<N; i++)
    if(digit_summ(i) == K)
    A.push_back(i);

    for(int i=0; i<A.size (); i++)
    cout << i+1 << ". " << A[i] << endl;

    return 0;
    }
    Ответ отправил: Терсков Сергей (статус: Специалист)
    Ответ отправлен: 17.04.2009, 08:15

    Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 247682 на номер 1151 (Россия) | Еще номера >>
  • Отправить WebMoney:
  • Вам помогли? Пожалуйста, поблагодарите эксперта за это!

    Оценка за ответ: 5
    Комментарий оценки:
    Большое спасибо! Красивый и лаконичный код.


    Вы имеете возможность оценить этот выпуск рассылки.
    Нам очень важно Ваше мнение!
    Оценить этот выпуск рассылки >>

    Отправить сообщение в эту рассылку:


    Форма НЕ работает в почтовых программах The BAT! и MS Outlook (кроме версии 2003+)!
    Чтобы отправить сообщение в рассылку, откройте это письмо в браузере.

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров >>

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2009, Портал RusFAQ.ru, Россия, Москва.
    Авторское право: ООО "Мастер-Эксперт Про"
    Техподдержка портала, тел.: +7 (926) 535-23-31
    Хостинг: "Московский хостер"
    Поддержка: "Московский дизайнер"
    Авторские права | Реклама на портале

    ∙ Версия системы: 5.13 от 01.12.2008

    Яндекс Rambler's Top100
    RusFAQ.ru | MosHoster.ru | MosDesigner.ru
    RusIRC.ru | Kalashnikoff.ru | RadioLeader.ru

    В избранное