From f5929eaf624560217618c83a370dd52086e5a29a Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 26 Aug 2016 14:17:20 +0200 Subject: Add a sudoku example Change-Id: I08a0c053a195dd55e6ff796b89a19ee160eb152d Reviewed-by: Erik Verbruggen --- examples/scxml/scxml.pro | 1 + .../scxml/sudoku/data/nearly-solved-sudoku.data | 9 + examples/scxml/sudoku/data/sudoku.data | 9 + examples/scxml/sudoku/main.cpp | 66 ++++++ examples/scxml/sudoku/mainwindow.cpp | 237 +++++++++++++++++++++ examples/scxml/sudoku/mainwindow.h | 81 +++++++ examples/scxml/sudoku/sudoku.js | 130 +++++++++++ examples/scxml/sudoku/sudoku.pro | 19 ++ examples/scxml/sudoku/sudoku.qrc | 8 + examples/scxml/sudoku/sudoku.scxml | 114 ++++++++++ 10 files changed, 674 insertions(+) create mode 100644 examples/scxml/sudoku/data/nearly-solved-sudoku.data create mode 100644 examples/scxml/sudoku/data/sudoku.data create mode 100644 examples/scxml/sudoku/main.cpp create mode 100644 examples/scxml/sudoku/mainwindow.cpp create mode 100644 examples/scxml/sudoku/mainwindow.h create mode 100644 examples/scxml/sudoku/sudoku.js create mode 100644 examples/scxml/sudoku/sudoku.pro create mode 100644 examples/scxml/sudoku/sudoku.qrc create mode 100644 examples/scxml/sudoku/sudoku.scxml (limited to 'examples') diff --git a/examples/scxml/scxml.pro b/examples/scxml/scxml.pro index 081304f..8da9db6 100644 --- a/examples/scxml/scxml.pro +++ b/examples/scxml/scxml.pro @@ -7,6 +7,7 @@ qtHaveModule(widgets) { SUBDIRS += mediaplayer-widgets-dynamic SUBDIRS += calculator-widgets SUBDIRS += pinball + SUBDIRS += sudoku } qtHaveModule(qml) { diff --git a/examples/scxml/sudoku/data/nearly-solved-sudoku.data b/examples/scxml/sudoku/data/nearly-solved-sudoku.data new file mode 100644 index 0000000..0e5c31f --- /dev/null +++ b/examples/scxml/sudoku/data/nearly-solved-sudoku.data @@ -0,0 +1,9 @@ +0, 3, 5, 2, 6, 9, 7, 8, 1 +6, 8, 2, 5, 7, 1, 4, 9, 3 +1, 9, 7, 8, 3, 4, 5, 6, 2 +8, 2, 6, 1, 9, 5, 3, 4, 7 +3, 7, 4, 6, 8, 2, 9, 1, 5 +9, 5, 1, 7, 4, 3, 6, 2, 8 +5, 1, 9, 3, 2, 6, 8, 7, 4 +2, 4, 8, 9, 5, 7, 1, 3, 6 +7, 6, 3, 4, 1, 8, 2, 5, 9 diff --git a/examples/scxml/sudoku/data/sudoku.data b/examples/scxml/sudoku/data/sudoku.data new file mode 100644 index 0000000..342fdf0 --- /dev/null +++ b/examples/scxml/sudoku/data/sudoku.data @@ -0,0 +1,9 @@ +0, 0, 0, 2, 6, 0, 7, 0, 1 +6, 8, 0, 0, 7, 0, 0, 9, 0 +1, 9, 0, 0, 0, 4, 5, 0, 0 +8, 2, 0, 1, 0, 0, 0, 4, 0 +0, 0, 4, 6, 0, 2, 9, 0, 0 +0, 5, 0, 0, 0, 3, 0, 2, 8 +0, 0, 9, 3, 0, 0, 0, 7, 4 +0, 4, 0, 0, 5, 0, 0, 3, 6 +7, 0, 3, 0, 1, 8, 0, 0, 0 diff --git a/examples/scxml/sudoku/main.cpp b/examples/scxml/sudoku/main.cpp new file mode 100644 index 0000000..0af8d72 --- /dev/null +++ b/examples/scxml/sudoku/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtScxml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sudoku.h" +#include "mainwindow.h" + +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + Sudoku machine; + MainWindow mainWindow(&machine); + + machine.start(); + mainWindow.show(); + return app.exec(); +} diff --git a/examples/scxml/sudoku/mainwindow.cpp b/examples/scxml/sudoku/mainwindow.cpp new file mode 100644 index 0000000..574b5ca --- /dev/null +++ b/examples/scxml/sudoku/mainwindow.cpp @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtScxml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int Size = 9; + +QT_USE_NAMESPACE + +static QVariantList emptyRow() +{ + QVariantList row; + for (int i = 0; i < Size; i++) + row.append(QVariant(0)); + return row; +} + +static QVariantMap readSudoku(const QString &fileName) +{ + QFile input(fileName); + input.open(QIODevice::ReadOnly | QIODevice::Text); + QTextStream str(&input); + const QString data = str.readAll(); + + QVariantList initRowsVariant; + const QStringList rows = data.split(QLatin1Char('\n')); + for (int i = 0; i < Size; i++) { + if (i < rows.count()) { + QVariantList initRowVariant; + const QStringList row = rows.at(i).split(QLatin1Char(',')); + for (int j = 0; j < Size; j++) { + const int val = j < row.count() + ? row.at(j).toInt() % (Size + 1) : 0; + initRowVariant.append(val); + } + initRowsVariant.append(QVariant(initRowVariant)); + } else { + initRowsVariant.append(QVariant(emptyRow())); + } + } + + QVariantMap dataVariant; + dataVariant.insert(QStringLiteral("initState"), initRowsVariant); + + return dataVariant; +} + +MainWindow::MainWindow(QScxmlStateMachine *machine, QWidget *parent) : + QWidget(parent), + m_machine(machine) +{ + const QVector initVector(Size, nullptr); + m_buttons = QVector >(Size, initVector); + + QGridLayout *layout = new QGridLayout(this); + + for (int i = 0; i < Size; i++) { + for (int j = 0; j < Size; j++) { + QToolButton *button = new QToolButton(this); + button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout->addWidget(button, i + i / 3, j + j / 3); + m_buttons[i][j] = button; + connect(button, &QToolButton::clicked, [this, i, j] () { + QVariantMap data; + data.insert(QStringLiteral("x"), i); + data.insert(QStringLiteral("y"), j); + m_machine->submitEvent("tap", data); + }); + } + } + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 2; j++) { + QFrame *hFrame = new QFrame(this); + hFrame->setFrameShape(QFrame::HLine); + layout->addWidget(hFrame, 4 * j + 3, 4 * i, 1, 3); + + QFrame *vFrame = new QFrame(this); + vFrame->setFrameShape(QFrame::VLine); + layout->addWidget(vFrame, 4 * i, 4 * j + 3, 3, 1); + } + } + + m_startButton = new QToolButton(this); + m_startButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_startButton->setText(tr("Start")); + layout->addWidget(m_startButton, Size + 3, 0, 1, 3); + + connect(m_startButton, &QAbstractButton::clicked, + [this] { + if (m_machine->isActive("playing")) + m_machine->submitEvent("stop"); + else + m_machine->submitEvent("start"); + }); + + m_label = new QLabel(tr("unsolved")); + m_label->setAlignment(Qt::AlignCenter); + layout->addWidget(m_label, Size + 3, 4, 1, 3); + + m_undoButton = new QToolButton(this); + m_undoButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_undoButton->setText(tr("Undo")); + layout->addWidget(m_undoButton, Size + 3, 8, 1, 3); + + connect(m_undoButton, &QAbstractButton::clicked, + [this] { + m_machine->submitEvent("undo"); + }); + + m_chooser = new QComboBox(this); + layout->addWidget(m_chooser, Size + 4, 0, 1, 11); + + QDir dataDir(QLatin1String(":/data")); + QFileInfoList sudokuFiles = dataDir.entryInfoList(QStringList() << "*.data"); + foreach (const QFileInfo &sudokuFile, sudokuFiles) + m_chooser->addItem(sudokuFile.completeBaseName(), sudokuFile.absoluteFilePath()); + + connect(m_chooser, static_cast(&QComboBox::currentIndexChanged), + [this] (int index) { + const QString sudokuFile = m_chooser->itemData(index).toString(); + const QVariantMap initValues = readSudoku(sudokuFile); + m_machine->submitEvent("setup", initValues); + }); + + const QVariantMap initValues = readSudoku(m_chooser->itemData(0).toString()); + m_machine->setInitialValues(initValues); + + m_machine->connectToState("playing", [this] (bool playing) { + if (playing) { + m_startButton->setText(tr("Stop")); + m_undoButton->setEnabled(true); + m_chooser->setEnabled(false); + } else { + m_startButton->setText(tr("Start")); + m_undoButton->setEnabled(false); + m_chooser->setEnabled(true); + } + }); + + m_machine->connectToState("solved", [this] (bool solved) { + if (solved) + m_label->setText(tr("SOLVED !!!")); + else + m_label->setText(tr("unsolved")); + }); + + m_machine->connectToEvent("updateGUI", [this] (const QScxmlEvent &event) { + const QVariant data = event.data(); + + const QVariantList currentRows = data.toMap().value("currentState").toList(); + for (int i = 0; i < currentRows.count(); i++) { + const QVariantList row = currentRows.at(i).toList(); + for (int j = 0; j < row.count(); j++) { + const int value = row.at(j).toInt(); + const QString text = value ? QString::number(value) : QString(); + m_buttons[i][j]->setText(text); + } + } + + const bool active = m_machine->isActive("playing"); + + const QVariantList initRows = data.toMap().value("initState").toList(); + for (int i = 0; i < initRows.count(); i++) { + const QVariantList row = initRows.at(i).toList(); + for (int j = 0; j < row.count(); j++) { + const int value = row.at(j).toInt(); + const bool enabled = !value && active; // enable only zeroes from initState + m_buttons[i][j]->setEnabled(enabled); + } + } + }); + + setLayout(layout); +} + +MainWindow::~MainWindow() +{ +} + diff --git a/examples/scxml/sudoku/mainwindow.h b/examples/scxml/sudoku/mainwindow.h new file mode 100644 index 0000000..99a0f1b --- /dev/null +++ b/examples/scxml/sudoku/mainwindow.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtScxml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +QT_BEGIN_NAMESPACE +class QToolButton; +class QScxmlStateMachine; +class QLabel; +class QComboBox; +QT_END_NAMESPACE + + +class MainWindow : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindow(QScxmlStateMachine *machine, QWidget *parent = 0); + ~MainWindow(); + +private: + QScxmlStateMachine *m_machine; + QVector > m_buttons; + QToolButton *m_startButton; + QToolButton *m_undoButton; + QLabel *m_label; + QComboBox *m_chooser; +}; + +#endif // MAINWINDOW_H diff --git a/examples/scxml/sudoku/sudoku.js b/examples/scxml/sudoku/sudoku.js new file mode 100644 index 0000000..afd9691 --- /dev/null +++ b/examples/scxml/sudoku/sudoku.js @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtScxml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +function restart() { + for (var i = 0; i < initState.length; i++) + currentState[i] = initState[i].slice(); + undoStack = []; +} + +function isValidPosition() { + var x = _event.data.x; + var y = _event.data.y; + if (x < 0 || x >= initState.length) + return false; + if (y < 0 || y >= initState.length) + return false; + if (initState[x][y] !== 0) + return false; + return true; +} + +function calculateCurrentState() { + if (isValidPosition() === false) + return + var x = _event.data.x; + var y = _event.data.y; + var currentValue = currentState[x][y]; + if (currentValue === initState.length) + currentValue = 0; + else + currentValue += 1; + currentState[x][y] = currentValue; + undoStack.push([x, y]); +} + +function isOK(numbers) { + var temp = []; + for (var i = 0; i < numbers.length; i++) { + var currentValue = numbers[i]; + if (currentValue === 0) + return false; + if (temp.indexOf(currentValue) >= 0) + return false; + temp.push(currentValue); + } + return true; +} + +function isSolved() { + for (var i = 0; i < currentState.length; i++) { + if (!isOK(currentState[i])) + return false; + + var column = []; + var square = []; + for (var j = 0; j < currentState[i].length; j++) { + column.push(currentState[j][i]); + square.push(currentState[Math.floor(i / 3) * 3 + Math.floor(j / 3)] + [i % 3 * 3 + j % 3]); + } + + if (!isOK(column)) + return false; + if (!isOK(square)) + return false; + } + return true; +} + +function undo() { + if (!undoStack.length) + return; + + var lastMove = undoStack.pop(); + var x = lastMove[0]; + var y = lastMove[1]; + var currentValue = currentState[x][y]; + if (currentValue === 0) + currentValue = initState.length; + else + currentValue -= 1; + currentState[x][y] = currentValue; +} diff --git a/examples/scxml/sudoku/sudoku.pro b/examples/scxml/sudoku/sudoku.pro new file mode 100644 index 0000000..0853a5e --- /dev/null +++ b/examples/scxml/sudoku/sudoku.pro @@ -0,0 +1,19 @@ +QT += widgets scxml + +CONFIG += c++11 + +STATECHARTS = sudoku.scxml + +SOURCES += \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + mainwindow.h + +RESOURCES += \ + sudoku.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/scxml/sudoku +INSTALLS += target diff --git a/examples/scxml/sudoku/sudoku.qrc b/examples/scxml/sudoku/sudoku.qrc new file mode 100644 index 0000000..6a15532 --- /dev/null +++ b/examples/scxml/sudoku/sudoku.qrc @@ -0,0 +1,8 @@ + + + sudoku.js + data/sudoku.data + data/nearly-solved-sudoku.data + + + diff --git a/examples/scxml/sudoku/sudoku.scxml b/examples/scxml/sudoku/sudoku.scxml new file mode 100644 index 0000000..ac447cc --- /dev/null +++ b/examples/scxml/sudoku/sudoku.scxml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3