// ==UserScript==
// @name 🎴配对翻牌 - 摸鱼小游戏
// @namespace https://www.dominickk.top/
// @supportURL https://github.com/Dominic-KK/PairMatchingGame/issues
// @version 0.1.1
// @description 一个可以在任何网页上玩的配对翻牌游戏,适合摸鱼时放松
// @author 🌹Dominic·KK🌹
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @run-at document-end
// ==/UserScript==
/* ==UserConfig==
基础设置:
MiniBtnTitle:
title: 入口按钮文本
description: 默认:翻牌摸鱼小游戏
default: 翻牌摸鱼小游戏
==/UserConfig== */
!(function () {
"use strict";
const e = ["🍎", "🍌", "🍒", "🍇", "🍊", "🍑", "🍓", "🥝"],
n = e.length;
let t,
m = !1,
o = [],
a = 0,
d = 0,
r = 0,
i = !0,
c = 3,
l = GM_getValue("基础设置.MiniBtnTitle") || "翻牌摸鱼小游戏";
if ("undefined" != typeof GM_getValue) {
const e = GM_getValue("MiniBtnTitle");
e && (l = e);
} else {
const e = localStorage.getItem("MiniBtnTitle");
e && (l = e);
}
function s() {
const r = document.getElementById("memory-game-board");
r.innerHTML = "";
const c = [];
e.forEach((e) => {
c.push(e, e);
}),
(function (e) {
for (let n = e.length - 1; n > 0; n--) {
const t = Math.floor(Math.random() * (n + 1));
[e[n], e[t]] = [e[t], e[n]];
}
})(c),
c.forEach((e, c) => {
const l = document.createElement("div");
(l.className = "memory-game-card"),
(l.dataset.index = c),
(l.dataset.symbol = e),
(l.innerHTML = `\n
\n `),
l.addEventListener("click", () =>
(function (e) {
m || (g(), (m = !0));
if (
!i ||
e.classList.contains("flipped") ||
e.classList.contains("matched")
)
return;
if ((e.classList.add("flipped"), o.push(e), 2 === o.length)) {
(i = !1),
d++,
(document.getElementById("memory-game-moves").textContent =
d);
const e = o[0],
m = o[1];
e.dataset.symbol === m.dataset.symbol
? (e.classList.add("matched"),
m.classList.add("matched"),
a++,
(document.getElementById(
"memory-game-matches"
).textContent = `${a}/${n}`),
(o = []),
(i = !0),
a === n &&
(clearInterval(t),
(document.getElementById(
"memory-game-final-time"
).textContent =
document.getElementById(
"memory-game-timer"
).textContent),
(document.getElementById(
"memory-game-final-moves"
).textContent = d),
setTimeout(() => {
(document.getElementById(
"memory-game-overlay"
).style.display = "block"),
(document.getElementById(
"memory-game-message"
).style.display = "block");
}, 1e3),
"undefined" != typeof GM_setValue
? GM_setValue("memoryGameState", null)
: localStorage.removeItem("memoryGameState")),
u())
: setTimeout(() => {
e.classList.remove("flipped"),
m.classList.remove("flipped"),
(o = []),
(i = !0),
u();
}, 1e3);
}
})(l)
),
r.appendChild(l);
});
}
function g() {
clearInterval(t),
(r = 0),
y(),
(t = setInterval(() => {
r++, y(), r % 60 == 0 && u();
}, 1e3));
}
function y() {
const e = Math.floor(r / 60)
.toString()
.padStart(2, "0"),
n = (r % 60).toString().padStart(2, "0");
document.getElementById("memory-game-timer").textContent = `${e}:${n}`;
}
function p() {
if (c <= 0) return;
c--,
(document.getElementById("memory-game-hint").textContent = `提示 (${c})`),
0 === c && (document.getElementById("memory-game-hint").disabled = !0);
const e = Array.from(
document.querySelectorAll(".memory-game-card:not(.matched)")
),
n = e.filter((e) => !e.classList.contains("flipped"));
if (n.length > 0) {
const t = n[Math.floor(Math.random() * n.length)],
m = t.dataset.symbol,
o = e.find(
(e) =>
e !== t &&
e.dataset.symbol === m &&
!e.classList.contains("flipped")
);
t.classList.add("flipped"),
o && o.classList.add("flipped"),
setTimeout(() => {
t.classList.remove("flipped"), o && o.classList.remove("flipped");
}, 1e3);
}
}
function u() {
const e = {
flippedCards: Array.from(
document.querySelectorAll(".memory-game-card.flipped:not(.matched)")
).map((e) => e.dataset.index),
matchedCards: Array.from(
document.querySelectorAll(".memory-game-card.matched")
).map((e) => e.dataset.index),
moves: d,
seconds: r,
hintCount: c,
gameStarted: m,
};
"undefined" != typeof GM_setValue
? GM_setValue("memoryGameState", JSON.stringify(e))
: localStorage.setItem("memoryGameState", JSON.stringify(e));
}
!(function () {
const e = document.getElementById("memory-game-container"),
u = document.getElementById("memory-game-minimized"),
h = document.getElementById("memory-game-message");
e && e.remove(), u && u.remove(), h && h.remove();
const f = document.createElement("style");
(f.textContent =
"\n #memory-game-container {\n position: fixed;\n top: 20px;\n right: 20px;\n width: 320px;\n background: #f5f5f5;\n border-radius: 10px;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n z-index: 10000;\n font-family: Arial, sans-serif;\n overflow: hidden;\n border: 1px solid #ddd;\n display: none; /* 默认隐藏 */\n }\n \n #memory-game-header {\n background: #2c3e50;\n color: white;\n padding: 10px 15px;\n cursor: move;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n \n #memory-game-title {\n font-weight: bold;\n font-size: 16px;\n }\n \n #memory-game-controls {\n display: flex;\n gap: 5px;\n }\n \n .memory-game-btn {\n background: rgba(255, 255, 255, 0.2);\n border: none;\n color: white;\n width: 24px;\n height: 24px;\n border-radius: 3px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n }\n \n .memory-game-btn:hover {\n background: rgba(255, 255, 255, 0.3);\n }\n \n #memory-game-content {\n padding: 15px;\n position: relative;\n }\n \n #memory-game-minimized {\n display: block; /* 默认显示 */\n background: #2c3e50;\n color: white;\n padding: 8px 12px;\n border-radius: 5px;\n cursor: pointer;\n font-size: 12px;\n position: fixed;\n top: 20px;\n right: 20px;\n z-index: 10000;\n box-shadow: 0 2px 5px rgba(0,0,0,0.2);\n user-select: none;\n white-space: nowrap; /* 防止文本换行 */\n text-align: center;\n }\n \n #memory-game-minimized:hover {\n background: #34495e;\n }\n \n .memory-game-info {\n display: flex;\n justify-content: space-between;\n margin-bottom: 15px;\n background: white;\n padding: 8px;\n border-radius: 5px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .memory-game-info-item {\n text-align: center;\n flex: 1;\n }\n \n .memory-game-info-label {\n font-size: 12px;\n color: #666;\n }\n \n .memory-game-info-value {\n font-size: 18px;\n font-weight: bold;\n color: #2c3e50;\n }\n \n .memory-game-board {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 5px;\n margin-bottom: 15px;\n }\n \n .memory-game-card {\n aspect-ratio: 1;\n perspective: 1000px;\n cursor: pointer;\n }\n \n .memory-game-card-inner {\n position: relative;\n width: 100%;\n height: 100%;\n text-align: center;\n transition: transform 0.5s;\n transform-style: preserve-3d;\n }\n \n .memory-game-card.flipped .memory-game-card-inner {\n transform: rotateY(180deg);\n }\n \n .memory-game-card-front, .memory-game-card-back {\n position: absolute;\n width: 100%;\n height: 100%;\n backface-visibility: hidden;\n border-radius: 5px;\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 20px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n .memory-game-card-front {\n background: #3498db;\n color: white;\n transform: rotateY(180deg);\n }\n \n .memory-game-card-back {\n background: #2c3e50;\n }\n \n .memory-game-card.matched .memory-game-card-front {\n background: #2ecc71;\n }\n \n .memory-game-controls {\n display: flex;\n justify-content: center;\n gap: 10px;\n }\n \n .memory-game-action-btn {\n padding: 8px 15px;\n border: none;\n border-radius: 5px;\n background: #3498db;\n color: white;\n font-size: 14px;\n cursor: pointer;\n transition: background 0.3s;\n }\n \n .memory-game-action-btn:hover {\n background: #2980b9;\n }\n \n .memory-game-action-btn.restart {\n background: #e74c3c;\n }\n \n .memory-game-action-btn.restart:hover {\n background: #c0392b;\n }\n \n /* 修改消息框样式,使其在游戏容器内居中 */\n .memory-game-message {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: white;\n padding: 20px;\n border-radius: 10px;\n box-shadow: 0 5px 15px rgba(0,0,0,0.3);\n z-index: 10001;\n text-align: center;\n display: none;\n width: 90%;\n max-width: 280px;\n }\n \n .memory-game-message h3 {\n margin-top: 0;\n color: #2c3e50;\n }\n \n .memory-game-message p {\n margin: 10px 0;\n }\n \n .memory-game-message button {\n margin-top: 10px;\n }\n \n /* 添加遮罩层,使游戏内容变暗 */\n .memory-game-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n display: none;\n z-index: 10000;\n }\n "),
document.head.appendChild(f);
const x = document.createElement("div");
x.id = "memory-game-container";
const b = document.createElement("div");
b.id = "memory-game-header";
const E = document.createElement("div");
(E.id = "memory-game-title"), (E.textContent = "配对翻牌游戏");
const v = document.createElement("div");
v.id = "memory-game-controls";
const C = document.createElement("button");
(C.className = "memory-game-btn"),
(C.id = "memory-game-minimize"),
(C.textContent = "−");
const I = document.createElement("button");
(I.className = "memory-game-btn"),
(I.id = "memory-game-close"),
(I.textContent = "×"),
v.appendChild(C),
v.appendChild(I),
b.appendChild(E),
b.appendChild(v);
const B = document.createElement("div");
B.id = "memory-game-content";
const k = document.createElement("div");
(k.className = "memory-game-overlay"), (k.id = "memory-game-overlay");
const w = document.createElement("div");
w.className = "memory-game-info";
const L = document.createElement("div");
L.className = "memory-game-info-item";
const S = document.createElement("div");
(S.className = "memory-game-info-label"), (S.textContent = "时间");
const z = document.createElement("div");
(z.className = "memory-game-info-value"),
(z.id = "memory-game-timer"),
(z.textContent = "00:00"),
L.appendChild(S),
L.appendChild(z);
const M = document.createElement("div");
M.className = "memory-game-info-item";
const N = document.createElement("div");
(N.className = "memory-game-info-label"), (N.textContent = "步数");
const G = document.createElement("div");
(G.className = "memory-game-info-value"),
(G.id = "memory-game-moves"),
(G.textContent = "0"),
M.appendChild(N),
M.appendChild(G);
const $ = document.createElement("div");
$.className = "memory-game-info-item";
const T = document.createElement("div");
(T.className = "memory-game-info-label"), (T.textContent = "匹配");
const V = document.createElement("div");
(V.className = "memory-game-info-value"),
(V.id = "memory-game-matches"),
(V.textContent = "0/8"),
$.appendChild(T),
$.appendChild(V),
w.appendChild(L),
w.appendChild(M),
w.appendChild($);
const _ = document.createElement("div");
(_.className = "memory-game-board"), (_.id = "memory-game-board");
const A = document.createElement("div");
A.className = "memory-game-controls";
const q = document.createElement("button");
(q.className = "memory-game-action-btn restart"),
(q.id = "memory-game-restart"),
(q.textContent = "重新开始");
const H = document.createElement("button");
(H.className = "memory-game-action-btn"),
(H.id = "memory-game-hint"),
(H.textContent = "提示 (3)"),
A.appendChild(q),
A.appendChild(H),
B.appendChild(w),
B.appendChild(_),
B.appendChild(A);
const Y = document.createElement("div");
(Y.className = "memory-game-message"), (Y.id = "memory-game-message");
const j = document.createElement("h3");
j.textContent = "恭喜!";
const D = document.createElement("p");
D.textContent = "你成功完成了游戏!";
const R = document.createElement("p");
R.innerHTML = '用时: 00:00';
const X = document.createElement("p");
X.innerHTML = '步数: 0';
const J = document.createElement("button");
(J.className = "memory-game-action-btn"),
(J.id = "memory-game-play-again"),
(J.textContent = "再玩一次"),
Y.appendChild(j),
Y.appendChild(D),
Y.appendChild(R),
Y.appendChild(X),
Y.appendChild(J),
B.appendChild(k),
B.appendChild(Y),
x.appendChild(b),
x.appendChild(B);
const O = document.createElement("div");
(O.id = "memory-game-minimized"),
(O.textContent = l),
document.body.appendChild(x),
document.body.appendChild(O),
s(),
(function () {
document
.getElementById("memory-game-restart")
.addEventListener("click", () => {
(m = !1),
(o = []),
(a = 0),
(d = 0),
(r = 0),
(c = 3),
(i = !0),
clearInterval(t),
(document.getElementById("memory-game-overlay").style.display =
"none"),
(document.getElementById("memory-game-message").style.display =
"none"),
(document.getElementById("memory-game-moves").textContent = d),
(document.getElementById(
"memory-game-matches"
).textContent = `${a}/${n}`),
(document.getElementById("memory-game-timer").textContent =
"00:00"),
(document.getElementById(
"memory-game-hint"
).textContent = `提示 (${c})`),
(document.getElementById("memory-game-hint").disabled = !1),
s(),
"undefined" != typeof GM_setValue
? GM_setValue("memoryGameState", null)
: localStorage.removeItem("memoryGameState");
}),
document
.getElementById("memory-game-hint")
.addEventListener("click", p),
document
.getElementById("memory-game-play-again")
.addEventListener("click", () => {
(document.getElementById("memory-game-overlay").style.display =
"none"),
(document.getElementById("memory-game-message").style.display =
"none"),
document.getElementById("memory-game-restart").click();
}),
document
.getElementById("memory-game-minimize")
.addEventListener("click", () => {
(document.getElementById("memory-game-container").style.display =
"none"),
(document.getElementById(
"memory-game-minimized"
).style.display = "block");
}),
document
.getElementById("memory-game-close")
.addEventListener("click", () => {
document.getElementById("memory-game-container").remove(),
document.getElementById("memory-game-minimized").remove();
}),
document
.getElementById("memory-game-minimized")
.addEventListener("click", (e) => {
if (!e.target.isDragging) {
const e = document.getElementById("memory-game-minimized"),
n = document.getElementById("memory-game-container"),
t = e.getBoundingClientRect();
n.style.display = "block";
const m = n.getBoundingClientRect(),
o = window.innerWidth || document.documentElement.clientWidth,
a =
window.innerHeight || document.documentElement.clientHeight;
let d = t.left,
r = t.bottom + 5;
d + m.width > o && (d = o - m.width - 10) < 10 && (d = 10),
r + m.height > a &&
(r = t.top - m.height - 5) < 10 &&
(r = 10),
(n.style.left = `${d}px`),
(n.style.top = `${r}px`),
(n.style.right = "auto"),
(e.style.display = "none");
}
});
let e = !1,
l = { x: 0, y: 0 };
document
.getElementById("memory-game-header")
.addEventListener("mousedown", (n) => {
if (n.target.classList.contains("memory-game-btn")) return;
e = !0;
const t = document
.getElementById("memory-game-container")
.getBoundingClientRect();
(l.x = n.clientX - t.left), (l.y = n.clientY - t.top);
}),
document.addEventListener("mousemove", (n) => {
if (!e) return;
const t = document.getElementById("memory-game-container");
(t.style.left = n.clientX - l.x + "px"),
(t.style.top = n.clientY - l.y + "px"),
(t.style.right = "auto");
}),
document.addEventListener("mouseup", () => {
e = !1;
});
let g = !1,
y = { x: 0, y: 0 };
document
.getElementById("memory-game-minimized")
.addEventListener("mousedown", (e) => {
(g = !0), (e.target.isDragging = !0);
const n = document
.getElementById("memory-game-minimized")
.getBoundingClientRect();
(y.x = e.clientX - n.left),
(y.y = e.clientY - n.top),
e.preventDefault();
}),
document.addEventListener("mousemove", (e) => {
if (!g) return;
const n = document.getElementById("memory-game-minimized");
(n.style.left = e.clientX - y.x + "px"),
(n.style.top = e.clientY - y.y + "px"),
(n.style.right = "auto");
}),
document.addEventListener("mouseup", () => {
(g = !1),
setTimeout(() => {
const e = document.getElementById("memory-game-minimized");
e && (e.isDragging = !1);
}, 100);
});
})(),
(function () {
let e = null;
if (
(e =
"undefined" != typeof GM_getValue
? GM_getValue("memoryGameState")
: localStorage.getItem("memoryGameState"))
)
try {
const t = JSON.parse(e);
(d = t.moves || 0),
(r = t.seconds || 0),
(c = t.hintCount || 3),
(m = t.gameStarted || !1),
(document.getElementById("memory-game-moves").textContent = d),
(document.getElementById("memory-game-matches").textContent = `${
t.matchedCards ? t.matchedCards.length / 2 : 0
}/${n}`),
(document.getElementById(
"memory-game-hint"
).textContent = `提示 (${c})`),
m ? g() : y(),
t.matchedCards &&
t.matchedCards.forEach((e) => {
const n = document.querySelector(
`.memory-game-card[data-index="${e}"]`
);
n && n.classList.add("matched", "flipped");
}),
t.flippedCards &&
(t.flippedCards.forEach((e) => {
const n = document.querySelector(
`.memory-game-card[data-index="${e}"]`
);
n &&
!n.classList.contains("matched") &&
n.classList.add("flipped");
}),
(o = Array.from(
document.querySelectorAll(
".memory-game-card.flipped:not(.matched)"
)
))),
(a = t.matchedCards ? t.matchedCards.length / 2 : 0);
} catch (e) {
console.error("加载游戏状态失败:", e);
}
})();
})();
})();