Добавил:
Только когда поступишь в технический вуз поймешь на сколько ты гуманитарий Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Готовое_КР_Быки_и_коровы

.pdf
Скачиваний:
0
Добавлен:
07.06.2025
Размер:
644.29 Кб
Скачать

ЗАКЛЮЧЕНИЕ

В ходе выполнения курсовой работы была успешно разработана и реализована мобильная версия классической логической игры "Быки и коровы" для операционной системы "Аврора". Основным достижением проекта стало создание игрового движка на C++ с эффективными алгоритмами генерации секретных чисел с использованием алгоритма Фишера-Йетса и оптимизированного двухэтапного метода подсчёта результатов. Разработанный движок обеспечивает высокую производительность даже на устройствах с ограниченными ресурсами, что особенно важно для мобильной платформы.

Интерфейс приложения, реализованный на QML, полностью адаптирован под особенности ОС "Аврора", включая поддержку системных тем (светлой и тёмной),

жестов управления и стандартов безопасности. Особое внимание было уделено созданию интуитивно понятного пользовательского опыта: реализованы два режима ввода (экранная клавиатура и цифровая панель), гибкая система истории попыток с настройками сохранения ввода между играми, а также визуально привлекательные диалоговые окна с градиентным оформлением в морской цветовой гамме.

Ключевым преимуществом разработки стала интеграция с платформой

"Аврора" без зависимости от Android-эмуляции, что обеспечивает не только повышенную производительность, но и полное соответствие требованиям информационной безопасности российской ОС. Приложение демонстрирует потенциал платформы для создания современных, безопасных и производительных решений, соответствующих мировым стандартам.

23

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

1. Официальная документация ОС "Аврора". Разработка нативных

приложений. Версия 4.0. // ООО "Открытая мобильная платформа", 2024. URL:

https://auroraos.ru/dev/docs/ (дата обращения: 29.05.2025).

2.Разработка приложений для ОС "Аврора" на C++/Qt / Петров А.В., Иванова С.К. // Журнал "Системы высокой доступности". – 2023. – № 4. – С. 45-58.

3.Гибридная разработка с QML и C++ / Шмидт В.Ф. СПб.: БХВ-Петербург,

2024. – 416 с. ISBN 978-5-9775-4123-6.

4.Современные методы генерации случайных чисел / Кнут Д. Искусство программирования. Том 2. – М.: Вильямс, 2019. – 832 с.

5.Официальный репозиторий примеров для Aurora SDK / GitHub, 2024. URL: https://github.com/auroraos/aurora-examples (дата обращения: 29.05.2025).

24

ПРИЛОЖЕНИЯ

Приложение А – Исходный код программы.

25

Приложение А

Листинг А.1 – MainPage.qml

import QtQuick 2.0

import Sailfish.Silica 1.0 import Nemo.Notifications 1.0 import Game 1.0

ApplicationWindow { id: appWindow

initialPage: mainPage

property bool firstRun: true

readonly property color seaWave: "#2E8B57"

Page {

id: mainPage

allowedOrientations: Orientation.All

SilicaFlickable { anchors.fill: parent

contentHeight: contentColumn.height

Rectangle { anchors.fill: parent gradient: Gradient {

GradientStop { position: 0.0; color: seaWave } GradientStop { position: 1.0; color: "#1D3C34" }

}

 

}

 

Column {

 

id: contentColumn

 

width: parent.width

 

spacing: Theme.paddingLarge

 

visible: !appWindow.firstRun

 

PageHeader {

 

title: "Быки и Коровы"

 

titleColor: Theme.primaryColor

 

}

 

TextField {

 

id: manualInput

 

width: parent.width - 2*Theme.horizontalPageMargin

 

anchors.horizontalCenter: parent.horizontalCenter

 

placeholderText: "Введите 4 цифры"

 

color: Theme.primaryColor

 

inputMethodHints: Qt.ImhDigitsOnly

 

maximumLength: 4

 

validator: RegExpValidator {

 

regExp: /^(?!.*(\d).*\1)\d{4}$/

 

}

 

text: game.currentGuess

 

label: "Ваша догадка"

//

placeholderColor: "#A0D3D3"

 

onTextChanged: {

 

if(text !== game.currentGuess) {

26

Продолжение Листинга А.1

game.setCurrentGuess(text)

}

}

background: Rectangle { color: "transparent"

border.color: Theme.primaryColor radius: 5

}

}

Button {

text: "Проверить"

anchors.horizontalCenter: parent.horizontalCenter enabled: game.currentGuess.length === 4 onClicked: game.checkGuess()

color: seaWave highlighted: true width: parent.width/2

}

Grid {

width: parent.width - 2*Theme.horizontalPageMargin columns: 5

spacing: Theme.paddingSmall anchors.horizontalCenter: parent.horizontalCenter

Repeater { model: 10 Button {

width: parent.width/5 - Theme.paddingSmall height: width

text: index

enabled: game.usedDigits.indexOf(text) === -1 &&

game.currentGuess.length < 4

onClicked: game.addDigit(text) color: "#1D3C34"

highlighted: true Label {

text: parent.text

color: Theme.primaryColor font.pixelSize: Theme.fontSizeLarge anchors.centerIn: parent

}

}

}

Button {

width: parent.width/5 - Theme.paddingSmall height: width

text: " "

onClicked: game.removeDigit() color: "#1D3C34"

highlighted: true Label {

text: parent.text

color: Theme.primaryColor font.pixelSize: Theme.fontSizeLarge anchors.centerIn: parent

27

Продолжение Листинга А.1

}

}

}

Repeater {

model: game.saveHistory ? game.history : (game.history.length > 0 ? [game.history[game.history.length-1]] : [])

delegate: ListItem { width: parent.width

contentHeight: Theme.itemSizeSmall

Rectangle { anchors.fill: parent color: "#1D3C34" opacity: 0.8

radius: 5

}

Label {

text: modelData anchors.centerIn: parent color: Theme.primaryColor

font.pixelSize: Theme.fontSizeSmall

}

}

}

}

}

Dialog {

id: firstRunDialog anchors.fill: parent canAccept: true

visible: appWindow.firstRun

background: Rectangle { color: seaWave radius: 15

}

Column {

anchors.fill: parent spacing: Theme.paddingLarge PageHeader {

title: "Добро пожаловать!" titleColor: Theme.primaryColor

}

TextSwitch {

text: "Сохранять историю попыток?" checked: false

onCheckedChanged: game.saveHistory = checked

}

Button {

text: "Начать игру"

anchors.horizontalCenter: parent.horizontalCenter onClicked: {

appWindow.firstRun = false

28

Продолжение Листинга А.1

firstRunDialog.accept()

game.newGame()

}

color: Theme.primaryColor highlighted: true

}

}

}

// Диалог победы

Dialog {

id: victoryDialog anchors.fill: parent canAccept: true background: Rectangle {

color: seaWave radius: 15

}

Column {

width: parent.width spacing: Theme.paddingLarge

PageHeader {

title: "ПОБЕДА!"

titleColor: Theme.primaryColor

}

Text {

text: "Хотите сохранять историю для следующей игры?" width: parent.width

horizontalAlignment: Text.AlignHCenter color: Theme.primaryColor font.pixelSize: Theme.fontSizeMedium

}

Row {

width: parent.width spacing: Theme.paddingLarge

Button {

text: "Да"

width: parent.width/2 - Theme.paddingLarge onClicked: {

game.saveHistory = true victoryDialog.accept() game.newGame()

}

color: "#1D3C34" highlighted: true

}

Button {

text: "Нет"

width: parent.width/2 - Theme.paddingLarge onClicked: {

game.saveHistory = false victoryDialog.accept() game.newGame()

}

29

Продолжение Листинга А.1

color: "#1D3C34" highlighted: true

}

}

}

}

}

GameEngine { id: game

onError: notification.show(message) onVictory: victoryDialog.open()

}

Notification {

id: notification expireTimeout: 3000

}

}

Листинг А.2 – GameEngine.cpp

#include "GameEngine.h" #include <QDateTime> #include <QDebug> #include <QSet>

GameEngine::GameEngine(QObject *parent) : QObject(parent)

{

qsrand(QDateTime::currentMSecsSinceEpoch());

}

void GameEngine::newGame()

{

m_secret = generateSecret(); m_currentGuess.clear(); m_history.clear();

emit guessChanged(); emit historyChanged();

qDebug() << "New game started. Secret:" << m_secret;

}

QVector<int> GameEngine::generateSecret()

{

QVector<int> digits;

for(int i = 0; i < 10; ++i) digits.append(i);

// Алгоритм Фишера-Йетса for(int i = 0; i < 4; ++i) {

int j = i + qrand() % (10 - i); qSwap(digits[i], digits[j]);

}

return digits.mid(0, 4);

}

void GameEngine::setCurrentGuess(const QString &guess)

{

if(guess != m_currentGuess && guess.length() <= 4 &&

QRegExp("^(?!.*(\\d).*\\1)\\d*$").exactMatch(guess))

{

30

Продолжение Листинга А.2

{

m_currentGuess = guess; emit guessChanged();

}

}

void GameEngine::addDigit(const QString &digit)

{

if(m_currentGuess.length() < 4 && !m_currentGuess.contains(digit)) { setCurrentGuess(m_currentGuess + digit);

}

}

void GameEngine::removeDigit()

{

if(!m_currentGuess.isEmpty()) { setCurrentGuess(m_currentGuess.left(m_currentGuess.length()-1));

}

}

bool GameEngine::validate() const

{

if(m_currentGuess.length() != 4) return false;

QSet<QChar> uniqueChars;

for(const QChar &c : m_currentGuess) { uniqueChars.insert(c);

}

return uniqueChars.size() == 4;

}

void GameEngine::checkGuess()

{

if(!validate()) {

emit error("Некорректный ввод!\nИспользуйте 4 уникальные цифры"); return;

}

processGuess();

}

void GameEngine::processGuess()

{

QVector<int> guessDigits;

for(const QChar &c : m_currentGuess) guessDigits << c.digitValue();

int bulls = 0, cows = 0; QVector<int> secretCopy = m_secret;

// Подсчет быков

for(int i = 0; i < 4; ++i) { if(guessDigits[i] == secretCopy[i]) {

bulls++; secretCopy[i] = -1; guessDigits[i] = -2;

}

}

// Подсчет коров

31

Продолжение Листинга А.2

for(int i = 0; i < 4; ++i) { if(secretCopy.contains(guessDigits[i])) cows++;

}

QString result = QString("%1: %2 бык. / %3 кор.").arg(m_currentGuess).arg(bulls).arg(cows);

if(m_saveHistory) { m_history.append(result);

} else {

m_history = QStringList(result);

}

m_currentGuess.clear(); emit guessChanged(); emit historyChanged();

if(bulls == 4) { emit victory();

}

}

void GameEngine::clearHistory()

{

m_history.clear(); emit historyChanged();

}

QString GameEngine::currentGuess() const

{

return m_currentGuess;

}

QStringList GameEngine::history() const

{

return m_history;

}

QStringList GameEngine::usedDigits() const

{

return m_currentGuess.split("", QString::SkipEmptyParts);

}

bool GameEngine::saveHistory() const

{

return m_saveHistory;

}

void GameEngine::setSaveHistory(bool value)

{

if(m_saveHistory != value) { m_saveHistory = value; if(!m_saveHistory) m_history.clear(); emit saveHistoryChanged();

}

}

32