Chotto.app
Login
Sign Up
ES
App Name
kuyawa / minesweeper
App Icon in SVG
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"> <defs> <!-- Mine Body Path --> <circle id="mine-body" cx="0" cy="0" r="45" fill="#1A1A1A" /> <!-- Mine Spikes Group --> <g id="spikes" fill="#1A1A1A"> <polygon points="-8,-52 8,-52 0,-75" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(45)" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(90)" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(135)" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(180)" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(225)" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(270)" /> <polygon points="-8,-52 8,-52 0,-75" transform="rotate(315)" /> </g> <!-- Bevel Highlight for Tile --> <linearGradient id="tile-bevel" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.6" /> <stop offset="50%" stop-color="#C0C0C0" stop-opacity="0" /> <stop offset="100%" stop-color="#808080" stop-opacity="0.4" /> </linearGradient> </defs> <!-- Background: Classic Windows Gray --> <!-- <rect width="512" height="512" fill="#66aaff" rx="90" /> --> <!-- Main Tile Group (Centered) --> <g transform="translate(256, 256)"> <!-- Raised Tile Base --> <!-- <rect x="-110" y="-110" width="220" height="220" rx="16" fill="#D4D4D4" stroke="#808080" stroke-width="4" /> --> <!-- Inner Bevel Effect --> <!-- <rect x="-110" y="-110" width="220" height="220" rx="16" fill="#88ff88" pointer-events="none" /> --> <!-- The Mine --> <g transform="scale(2.5)"> <use href="#spikes" /> <use href="#mine-body" /> <!-- Mine Highlight (Glossy effect) --> <circle cx="-15" cy="-15" r="12" fill="#FFFFFF" opacity="0.25" /> </g> <!-- Subtle Drop Shadow under the Mine for depth --> <circle cx="0" cy="5" r="45" fill="#000000" opacity="0.15" filter="blur(4px)" /> </g> </svg>
HTML Content
<!DOCTYPE html> <html lang="en" data-theme="dark"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Minesweeper</title> <style> :root { --speed: 0.25s; } [data-theme="dark"] { --bg: #0c0c0c; --bg2: #141414; --card: #181818; --border: #252525; --fg: #e4e4e4; --muted: #6a6a6a; --accent: #e09030; --accent-h: #f0a840; --cell-hid: #242424; --cell-hov: #2e2e2e; --cell-rev: #111111; --danger: #d44040; --success: #38b868; --shadow: rgba(0,0,0,0.6); --overlay: rgba(6,6,6,0.8); --glow: rgba(224,144,48,0.06); --wrong-flag: #d44040; } [data-theme="light"] { --bg: #eeeae4; --bg2: #e2ded8; --card: #faf8f5; --border: #d0ccc4; --fg: #1a1816; --muted: #8a8680; --accent: #c07818; --accent-h: #d88820; --cell-hid: #d4d0ca; --cell-hov: #c8c4bc; --cell-rev: #f4f2ee; --danger: #c03030; --success: #28904c; --shadow: rgba(0,0,0,0.08); --overlay: rgba(238,234,228,0.85); --glow: rgba(192,120,24,0.05); --wrong-flag: #c03030; } *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} body{ font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,sans-serif; background:var(--bg);color:var(--fg); min-height:100vh;display:flex;flex-direction:column;align-items:center; transition:background var(--speed),color var(--speed); overflow-x:hidden; } /* Atmospheric background */ body::before{ content:'';position:fixed;inset:0;pointer-events:none;z-index:0; background: radial-gradient(ellipse 80% 60% at 25% 15%, var(--glow), transparent), radial-gradient(ellipse 60% 80% at 75% 85%, var(--glow), transparent); } /* Noise texture overlay */ body::after{ content:'';position:fixed;inset:0;pointer-events:none;z-index:0; opacity:0.025; background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-size:200px; } header{ position:relative;z-index:1;width:100%;max-width:740px; padding:20px 16px 0;display:flex;align-items:center;justify-content:space-between; } .logo{ font-size:21px;font-weight:800;letter-spacing:-0.6px; display:flex;align-items:center;gap:6px; } .logo-diamond{ display:inline-block;width:14px;height:14px; background:var(--accent);transform:rotate(45deg); border-radius:2px;flex-shrink:0; } @keyframes spin-diamond{ 0%{transform:rotate(45deg) scale(1)} 25%{transform:rotate(135deg) scale(1.05)} 50%{transform:rotate(225deg) scale(1)} 75%{transform:rotate(315deg) scale(0.95)} 100%{transform:rotate(405deg) scale(1)} } .logo span{color:var(--accent)} .theme-btn{ width:42px;height:42px;border:1px solid var(--border);border-radius:11px; background:var(--card);color:var(--fg);cursor:pointer; display:flex;align-items:center;justify-content:center; transition:all var(--speed);font-size:16px; } .theme-btn:hover{border-color:var(--accent);background:var(--cell-hid)} main{ position:relative;z-index:1;width:100%;max-width:740px; padding:16px 16px 48px;display:flex;flex-direction:column;align-items:center;gap:12px; } /* Controls row */ .ctrl-row{ width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap; } .diff-group{display:flex;gap:5px} .diff-btn{ padding:7px 14px;border:1px solid var(--border);border-radius:9px; background:var(--card);color:var(--muted);font-size:12.5px;font-weight:600; cursor:pointer;transition:all var(--speed);white-space:nowrap; font-family:inherit; } .diff-btn:hover{border-color:var(--accent);color:var(--fg)} .diff-btn.on{background:var(--accent);border-color:var(--accent);color:#000} .flag-btn{ padding:7px 14px;border:1px solid var(--border);border-radius:9px; background:var(--card);color:var(--muted);font-size:12.5px;font-weight:600; cursor:pointer;transition:all var(--speed);display:none;white-space:nowrap; font-family:inherit; } .flag-btn.on{background:var(--danger);border-color:var(--danger);color:#fff} @media(hover:none)and (pointer:coarse){.flag-btn{display:block}} /* Status bar */ .stat-bar{ width:100%;display:flex;align-items:center;justify-content:space-between; padding:10px 14px;background:var(--card);border:1px solid var(--border); border-radius:13px;box-shadow:0 2px 16px var(--shadow); } .stat-item{display:flex;align-items:center;gap:8px} .stat-ico{ width:34px;height:34px;border-radius:9px; display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:700; } .stat-ico.mines-ico{background:rgba(212,64,64,0.12);color:var(--danger)} .stat-ico.time-ico{background:rgba(224,144,48,0.12);color:var(--accent)} .stat-val{font-size:22px;font-weight:800;font-variant-numeric:tabular-nums;min-width:36px;letter-spacing:-0.5px} .reset-btn{ width:44px;height:44px;border:1px solid var(--border);border-radius:12px; background:var(--card);color:var(--fg);cursor:pointer;font-size:20px; display:flex;align-items:center;justify-content:center; transition:all 0.4s cubic-bezier(0.34,1.56,0.64,1);font-family:inherit; } .reset-btn:hover{border-color:var(--accent);transform:rotate(360deg)} /* Board */ .board-wrap{ display:flex;width:100%;overflow:auto;border-radius:14px; box-shadow:0 4px 28px var(--shadow);border:1px solid var(--border); background:var(--card);padding:6px; -webkit-overflow-scrolling:touch; } .board{ display:grid;gap:2px;margin:0 auto; user-select:none;-webkit-user-select:none; } .cell{ border:none;border-radius:4px;background:var(--cell-hid); cursor:pointer;display:flex;align-items:center;justify-content:center; font-size:13px;font-weight:700;transition:background 0.12s,transform 0.12s; position:relative;color:var(--fg);padding:0;font-family:inherit; } .cell:hover:not(.rev):not(.dead){background:var(--cell-hov);transform:scale(1.08);z-index:2} .cell:active:not(.rev):not(.dead){transform:scale(0.95)} .cell.rev{background:var(--cell-rev);cursor:default} .cell.rev.anim{animation:pop 0.22s cubic-bezier(0.34,1.56,0.64,1) both} @keyframes pop{ 0%{transform:scale(0.6);opacity:0.4} 100%{transform:scale(1);opacity:1} } .cell.flagged::after{content:'⚑';font-size:15px;color:var(--danger)} .cell.mine-hit{background:var(--danger)!important;animation:boom 0.35s ease-out both} @keyframes boom{ 0%{transform:scale(1)} 40%{transform:scale(1.35)} 100%{transform:scale(1)} } .cell.mine-show{background:rgba(212,64,64,0.08)} .cell.wrong-flag{color:var(--wrong-flag)!important;text-decoration:line-through} /* Number palette — high contrast, distinctive */ .cell.n1{color:#5aafff}.cell.n2{color:#48c870}.cell.n3{color:#ff6060} .cell.n4{color:#a870e0}.cell.n5{color:#e08030}.cell.n6{color:#20b8a0} .cell.n7{color:#e0e0e0}.cell.n8{color:#909090} /* Overlay */ .ov{ position:fixed;inset:0;background:var(--overlay);display:flex; align-items:center;justify-content:center;z-index:200; opacity:0;pointer-events:none;transition:opacity 0.3s; backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px); } .ov.show{opacity:1;pointer-events:all} .ov-card{ display: flex; flex-direction: column; background:var(--card);border:1px solid var(--border);border-radius:20px; padding:40px 36px;text-align:center;box-shadow:0 12px 48px var(--shadow); transform:scale(0.88) translateY(12px);transition:transform 0.35s cubic-bezier(0.34,1.56,0.64,1); max-width:340px;width:90%; } .ov.show .ov-card{transform:scale(1) translateY(0)} .ov-ico{font-size:44px;margin-bottom:14px;display:block;line-height:1} .ov-title{font-size:26px;font-weight:800;margin-bottom:6px;letter-spacing:-0.5px} .ov-sub{color:var(--muted);font-size:14px;margin-bottom:28px;line-height:1.6} .ov-btn{ padding:12px 36px;border:none;border-radius:11px; background:var(--accent);color:#000;font-size:14px;font-weight:700; cursor:pointer;transition:all var(--speed);font-family:inherit; } .ov-btn:hover{background:var(--accent-h);transform:translateY(-2px);box-shadow:0 4px 16px rgba(224,144,48,0.3)} .ov-clr { margin-top: 1rem; background-color: transparent; color: var(--accent); border: none; cursor:pointer; } /* Scrollbar */ .board-wrap::-webkit-scrollbar{height:5px;width:5px} .board-wrap::-webkit-scrollbar-track{background:var(--bg2);border-radius:3px} .board-wrap::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px} /* Focus visible */ .cell:focus-visible,.diff-btn:focus-visible,.reset-btn:focus-visible, .theme-btn:focus-visible,.flag-btn:focus-visible,.ov-btn:focus-visible{ outline:2px solid var(--accent);outline-offset:2px; } /* Reduced motion */ @media(prefers-reduced-motion:reduce){ *,*::before,*::after{animation-duration:0.01ms!important;transition-duration:0.01ms!important} } @media(max-width:520px){ .cell{font-size:10px;border-radius:3px} .cell.flagged::after{font-size:11px} .board-wrap{padding:4px} .board{gap:1px} header{padding:14px 12px 0} main{padding:10px 10px 36px} .stat-bar{padding:8px 10px} .stat-val{font-size:19px} .diff-btn,.flag-btn{padding:6px 10px;font-size:11.5px} .logo{font-size:18px} } </style> </head> <body> <header> <div class="logo"><span class="logo-diamond"></span>Mine<span>sweeper</span></div> <button class="theme-btn" id="themeBtn" aria-label="Toggle theme">☼</button> </header> <main> <div class="ctrl-row"> <div class="diff-group" role="radiogroup" aria-label="Difficulty"> <button class="diff-btn on" data-d="beginner" role="radio" aria-checked="true">Beginner</button> <button class="diff-btn" data-d="intermediate" role="radio" aria-checked="false">Intermediate</button> <button class="diff-btn" data-d="expert" role="radio" aria-checked="false">Expert</button> </div> <button class="flag-btn" id="flagBtn" aria-label="Toggle flag mode">Flag Mode</button> </div> <div class="stat-bar"> <div class="stat-item"> <div class="stat-ico mines-ico">✦</div> <span class="stat-val" id="mineDisp">10</span> </div> <button class="reset-btn" id="resetBtn" aria-label="New game">↻</button> <div class="stat-item"> <div class="stat-ico time-ico">◷</div> <span class="stat-val" id="timeDisp">0</span> </div> </div> <div class="board-wrap" id="boardWrap"> <div class="board" id="board" role="grid" aria-label="Minesweeper board"></div> </div> </main> <div class="ov" id="ov"> <div class="ov-card"> <span class="ov-ico" id="ovIco"></span> <div class="ov-title" id="ovTitle"></div> <div class="ov-sub" id="ovSub"></div> <button class="ov-btn" id="ovBtn">Play Again</button> <button class="ov-clr" id="ovClr">Back to Game</button> </div> </div> <script> (function(){ /* === Difficulty presets === */ var DIFF = { beginner: {r:9, c:9, m:10}, intermediate: {r:16, c:16, m:40}, expert: {r:30, c:16, m:99} }; /* === State === */ var diff='beginner', R, C, M; var grid=[], els=[]; var state='idle', flags=0, opened=0; var timer=null, secs=0, first=true, flagMode=false; /* === DOM refs === */ var boardEl=document.getElementById('board'), wrapEl=document.getElementById('boardWrap'), mineEl=document.getElementById('mineDisp'), timeEl=document.getElementById('timeDisp'), resetBtn=document.getElementById('resetBtn'), themeBtn=document.getElementById('themeBtn'), flagBtn=document.getElementById('flagBtn'), ov=document.getElementById('ov'), ovIco=document.getElementById('ovIco'), ovTitle=document.getElementById('ovTitle'), ovSub=document.getElementById('ovSub'), ovBtn=document.getElementById('ovBtn'), ovClr=document.getElementById('ovClr'), diffBtns=document.querySelectorAll('.diff-btn'); /* === Theme === */ function setTheme(t){ document.documentElement.setAttribute('data-theme',t); themeBtn.innerHTML=t==='dark'?'☼':'☾'; try{localStorage.setItem('ms-theme',t)}catch(e){} } themeBtn.onclick=function(){ setTheme(document.documentElement.getAttribute('data-theme')==='dark'?'light':'dark'); }; try{var st=localStorage.getItem('ms-theme');if(st)setTheme(st);else setTheme('dark')}catch(e){setTheme('dark')} /* === Difficulty === */ diffBtns.forEach(function(b){ b.onclick=function(){ diffBtns.forEach(function(x){x.classList.remove('on');x.setAttribute('aria-checked','false')}); b.classList.add('on');b.setAttribute('aria-checked','true'); diff=b.dataset.d; console.log('DIFF', diff) init(); }; }); /* === Flag mode === */ flagBtn.onclick=function(){ flagMode=!flagMode; flagBtn.classList.toggle('on',flagMode); }; /* === Timer === */ function startTimer(){ if(timer)return; timer=setInterval(function(){secs++;timeEl.textContent=secs},1000); } function stopTimer(){clearInterval(timer);timer=null} function resetTimer(){stopTimer();secs=0;timeEl.textContent='0'} /* === Overlay === */ function showOv(ico,title,sub){ ovIco.innerHTML=ico;ovTitle.textContent=title;ovSub.textContent=sub; ov.classList.add('show'); } function hideOv(){ov.classList.remove('show')} resetBtn.onclick=init; ovBtn.onclick=function(){hideOv();init()}; ovClr.onclick=function(){hideOv();}; /* === Mine count display === */ function updMines(){mineEl.textContent=M-flags} /* === Initialize === */ function init(){ var d=DIFF[diff];R=d.r;C=d.c;M=d.m; flags=0;opened=0;state='idle';first=true;flagMode=false; flagBtn.classList.remove('on'); resetTimer();updMines();hideOv(); /* Build grid data */ grid=[]; for(var r=0;r<R;r++){grid[r]=[];for(var c=0;c<C;c++)grid[r][c]={mine:false,rev:false,flag:false,adj:0}} buildDOM(); } /* === Build DOM board === */ function calcCellSize(){ var w=wrapEl.clientWidth-12; var s=Math.floor(w/C); var z=Math.max(18,Math.min(s,38)); //console.log('SIZE', z) z = z - 2 return z; } function buildDOM(){ boardEl.innerHTML='';els=[]; var sz=calcCellSize(); boardEl.style.gridTemplateColumns='repeat('+C+','+sz+'px)'; boardEl.style.gridTemplateRows='repeat('+R+','+sz+'px)'; for(var r=0;r<R;r++){ els[r]=[]; for(var c=0;c<C;c++){ var btn=document.createElement('button'); btn.className='cell'; btn.setAttribute('role','gridcell'); btn.setAttribute('aria-label','Row '+(r+1)+' Column '+(c+1)); bindCell(btn,r,c); boardEl.appendChild(btn); els[r][c]=btn; } } } function bindCell(btn,r,c){ var pt=null; btn.addEventListener('click',function(e){ e.preventDefault(); if(flagMode){doFlag(r,c);return} doClick(r,c); }); btn.addEventListener('contextmenu',function(e){ e.preventDefault();doFlag(r,c); }); /* Long-press for flag on touch */ btn.addEventListener('touchstart',function(e){ pt=setTimeout(function(){doFlag(r,c);pt=null},350); },{passive:true}); btn.addEventListener('touchend',function(){if(pt){clearTimeout(pt);pt=null}}); btn.addEventListener('touchmove',function(){if(pt){clearTimeout(pt);pt=null}},{passive:true}); } /* === Place mines after first click === */ function placeMines(sr,sc){ var safe={}; for(var dr=-1;dr<=1;dr++)for(var dc=-1;dc<=1;dc++){ var nr=sr+dr,nc=sc+dc; if(nr>=0&&nr<R&&nc>=0&&nc<C)safe[nr+','+nc]=1; } var placed=0; while(placed<M){ var r=Math.floor(Math.random()*R),c=Math.floor(Math.random()*C); if(!grid[r][c].mine&&!safe[r+','+c]){grid[r][c].mine=true;placed++} } /* Calculate adjacents */ for(var r2=0;r2<R;r2++)for(var c2=0;c2<C;c2++){ if(grid[r2][c2].mine)continue; var n=0; for(var dr2=-1;dr2<=1;dr2++)for(var dc2=-1;dc2<=1;dc2++){ if(!dr2&&!dc2)continue; var ar=r2+dr2,ac=c2+dc2; if(ar>=0&&ar<R&&ac>=0&&ac<C&&grid[ar][ac].mine)n++; } grid[r2][c2].adj=n; } } /* === Click === */ function doClick(r,c){ if(state==='won'||state==='lost')return; var cell=grid[r][c]; if(cell.rev||cell.flag)return; if(first){ first=false;state='playing'; placeMines(r,c);startTimer(); } if(cell.mine){gameOver(r,c);return} /* BFS reveal with staggered animation */ revealBFS(r,c); checkWin(); } /* === BFS Reveal with ripple delay === */ function revealBFS(sr,sc){ var queue=[[sr,sc,0]]; var visited={}; visited[sr+','+sc]=1; var batch=[]; while(queue.length){ var cur=queue.shift(); var r=cur[0],c=cur[1],dist=cur[2]; var cell=grid[r][c]; if(cell.rev||cell.flag||cell.mine)continue; cell.rev=true;opened++; batch.push({r:r,c:c,dist:dist,adj:cell.adj}); if(cell.adj===0){ for(var dr=-1;dr<=1;dr++)for(var dc=-1;dc<=1;dc++){ if(!dr&&!dc)continue; var nr=r+dr,nc=c+dc,key=nr+','+nc; if(nr>=0&&nr<R&&nc>=0&&nc<C&&!visited[key]){ visited[key]=1; queue.push([nr,nc,dist+1]); } } } } /* Apply DOM updates with staggered animation */ var maxDelay=Math.min(batch.length*8, 400); for(var i=0;i<batch.length;i++){ var b=batch[i]; var el=els[b.r][b.c]; el.classList.add('rev'); var delay=Math.min(b.dist*18, maxDelay); el.style.animationDelay=delay+'ms'; el.classList.add('anim'); if(b.adj>0){ el.textContent=b.adj; el.classList.add('n'+b.adj); } } /* Clean up anim class after animations finish */ setTimeout(function(){ for(var i=0;i<batch.length;i++){ els[batch[i].r][batch[i].c].classList.remove('anim'); els[batch[i].r][batch[i].c].style.animationDelay=''; } }, maxDelay+300); } /* === Flag === */ function doFlag(r,c){ if(state==='won'||state==='lost'||state==='idle')return; var cell=grid[r][c]; if(cell.rev)return; cell.flag=!cell.flag; flags+=cell.flag?1:-1; updMines(); var el=els[r][c]; el.classList.toggle('flagged',cell.flag); el.setAttribute('aria-label',cell.flag?'Flagged, Row '+(r+1)+' Column '+(c+1):'Row '+(r+1)+' Column '+(c+1)); checkWin(); } /* === Game Over === */ function gameOver(hr,hc){ state='lost';stopTimer(); /* Reveal mines with cascade from hit point */ var minePositions=[]; for(var r=0;r<R;r++)for(var c=0;c<C;c++){ if(grid[r][c].mine){ var d=Math.abs(r-hr)+Math.abs(c-hc); minePositions.push({r:r,c:c,d:d,hr:r===hr&&c===hc}); }else if(grid[r][c].flag){ /* Wrong flag */ els[r][c].classList.add('wrong-flag'); els[r][c].classList.add('dead'); } } minePositions.sort(function(a,b){return a.d-b.d}); minePositions.forEach(function(p,i){ var el=els[p.r][p.c]; el.classList.add('dead'); setTimeout(function(){ if(p.hr){ el.classList.add('mine-hit'); }else{ el.classList.add('mine-show'); } el.textContent='\u2726'; }, i*25); }); var totalTime=Math.min(minePositions.length*25+400, 1500); setTimeout(function(){ showOv('\u2726','Game Over','You hit a mine after '+secs+' second'+(secs!==1?'s':'')+'.'); }, totalTime); } /* === Check Win === */ function checkWin(){ if(opened===R*C-M){ state='won';stopTimer(); /* Auto-flag remaining */ for(var r=0;r<R;r++)for(var c=0;c<C;c++){ if(grid[r][c].mine&&!grid[r][c].flag){ grid[r][c].flag=true; els[r][c].classList.add('flagged'); flags++; } } updMines(); setTimeout(function(){ showOv('\u25C6','Victory','Cleared in '+secs+' second'+(secs!==1?'s':'')+'. Well played!'); },350); } } /* === Resize === */ var rto; window.addEventListener('resize',function(){ clearTimeout(rto); rto=setTimeout(function(){ var sz=calcCellSize(); boardEl.style.gridTemplateColumns='repeat('+C+','+sz+'px)'; boardEl.style.gridTemplateRows='repeat('+R+','+sz+'px)'; /* Restore visual state */ for(var r=0;r<R;r++)for(var c=0;c<C;c++){ var el=els[r][c],cell=grid[r][c]; el.className='cell';el.textContent=''; if(cell.rev){ el.classList.add('rev'); if(cell.adj>0){el.textContent=cell.adj;el.classList.add('n'+cell.adj)} } if(cell.flag)el.classList.add('flagged'); if(state==='lost'){ el.classList.add('dead'); if(cell.mine){el.classList.add('mine-show');el.textContent='\u2726'} else if(cell.flag)el.classList.add('wrong-flag'); } } },150); }); /* === Keyboard shortcuts === */ document.addEventListener('keydown',function(e){ if(e.key==='r'||e.key==='R')init(); if(e.key==='f'||e.key==='F'){ if('ontouchstart' in window){flagMode=!flagMode;flagBtn.classList.toggle('on',flagMode)} } }); /* === Close overlay on Escape === */ document.addEventListener('keydown',function(e){ if(e.key==='Escape'&&ov.classList.contains('show')){hideOv()} }); /* === Start === */ init(); })(); </script> </body> </html>
Cancel