Qt小例子学习52 - 卡片游戏
Card.qml
import QtQuick 2.0
import QtQuick.Layouts 1.3
Item {
id: card
Layout.fillWidth: true
Layout.fillHeight: true
property alias backImageSource: backImage.source
property alias flipped: flipable.flipped
property alias state: flipable.state
signal finished()
Flipable {
id: flipable
anchors.fill: parent
property alias backImageSource: backImage.source
property bool flipped: false
front: Rectangle {
anchors.fill: parent
color: '#965555'
radius: 12
border.width: 2
border.color: '#ffffff'
Image {
anchors { fill: parent; centerIn: parent }
fillMode: Image.PreserveAspectFit
source: 'qrc:/images/back.gif'
}
}
back: Rectangle {
anchors.fill: parent
color: '#965555'
radius: 12
border.width: 2
border.color: '#ffffff'
Image {
id: backImage
width: parent.width - 25
height: parent.height - 25
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
}
}
transform: Rotation {
id: rotation
origin.x: flipable.width / 2
origin.y: flipable.height / 2
axis.x: 0; axis.y: 1; axis.z: 0
angle: 0
}
states: [
State {
name: 'back'
PropertyChanges { target: rotation; angle: 180 }
when: flipable.flipped
},
State {
name: 'remove'
PropertyChanges {
target: card
visible: false
}
}
]
transitions: Transition {
NumberAnimation { target: rotation; property: 'angle'; duration: 400 }
onRunningChanged: {
if ((state == "back") && (!running))
finished()
}
}
MouseArea {
anchors.fill: parent
onClicked: card.flipped = true
}
}
}
GameArea.qml
import QtQuick 2.0
import QtQuick.Layouts 1.3
import './js/GameUtils.js' as GameUtils
GridLayout {
id: area
anchors.fill: parent
anchors.margins: 25
columns: (width < height) ? 4 : Math.round(repeater.model / 4)
rowSpacing: 5
columnSpacing: 5
property int imageCount: 10
property int repeatCount: (repeater.model > imageCount)
? repeater.model / imageCount : 1
property variant imageIndexes: GameUtils.generateCardIndexes(
imageCount, repeatCount)
property int lastIndex : -1
Repeater {
id: repeater
model: 40
Card {
id: card
backImageSource: 'qrc:/images/img_' + area.imageIndexes[index] + '.jpg'
onFinished: verify(index)
}
}
function verify(index){
if(lastIndex == -1){
lastIndex = index
return
}
area.enabled = false
var lastItem = repeater.itemAt(lastIndex)
var currentItem = repeater.itemAt(index)
if(lastItem.backImageSource === currentItem.backImageSource){
lastItem.state = "remove"
currentItem.state = "remove"
}
else{
lastItem.flipped = false
currentItem.flipped = false
}
if(repeater.model === 0){
console.log("Winning")
}
lastIndex = -1
area.enabled = true
}
}
GameUtils.js
.pragma library
function randomShuffle(array) {
var currentIndex, tmp;
for (var i = 0; i < array.length; i++) {
currentIndex = Math.floor(Math.random() * (i + 1));
tmp = array[i];
array[i] = array[currentIndex];
array[currentIndex] = tmp;
}
}
function generateCardIndexes(imageCount, repeatCount) {
var cardIndexes = [];
var i, j;
for (i = 0; i < imageCount; i++) {
for (j = 0; j < repeatCount; j++) {
cardIndexes.push(i + 1);
}
}
randomShuffle(cardIndexes);
return cardIndexes;
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr('Memory Game')
GameArea {}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}