// ==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
${e}
\n
\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); } })(); })(); })();