mirror of https://gitee.com/openkylin/batik.git
434 lines
15 KiB
XML
434 lines
15 KiB
XML
<?xml version="1.0" standalone="no"?>
|
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
|
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
|
|
<!--
|
|
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
-->
|
|
<!-- ====================================================================== -->
|
|
<!-- Minesweeper in SVG -->
|
|
<!-- -->
|
|
<!-- @author thomas.deweese@kodak.com -->
|
|
<!-- @version $Id$ -->
|
|
<!-- ====================================================================== -->
|
|
|
|
<svg width="450" height="500" viewBox="0 0 450 500"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
|
<script type="text/ecmascript">
|
|
<![CDATA[
|
|
//
|
|
// Global declarations
|
|
//
|
|
var mines0 = 8;
|
|
var mines1 = 40;
|
|
var mines2 = 99;
|
|
|
|
var boardSize = 1;
|
|
var numAcross = 16;
|
|
var numDown = 16;
|
|
var numMines = 40;
|
|
|
|
var correctFlags = 0;
|
|
var incorrectFlags = 0;
|
|
var minesLeft;
|
|
var board = document.getElementById("board")
|
|
var cover = document.getElementById("cover")
|
|
|
|
var boardArray = new Array(numAcross*numDown);
|
|
var shownArray = new Array(numAcross*numDown);
|
|
var flagArray = new Array(numAcross*numDown);
|
|
var isGameOver = true;
|
|
var xlinkNS = "http://www.w3.org/1999/xlink";
|
|
var svgNS = "http://www.w3.org/2000/svg";
|
|
|
|
function initBoard(evt) {
|
|
isGameOver = false;
|
|
minesLeft = numMines;
|
|
correctFlags = 0;
|
|
|
|
updateText("mines", "Mines Left: "+minesLeft);
|
|
updateText("boardsz", "Board Size: "+numAcross+"x"+numDown);
|
|
updateText("title", "");
|
|
updateText("working", "Working");
|
|
|
|
for(var y=0; y<numDown; y++) {
|
|
for(var x=0; x<numAcross; x++) {
|
|
boardArray[x+y*numAcross] = 0;
|
|
shownArray[x+y*numAcross] = false;
|
|
flagArray [x+y*numAcross] = false;
|
|
}
|
|
}
|
|
while (cover.lastChild != null) {
|
|
cover.removeChild(cover.lastChild);
|
|
}
|
|
while (board.lastChild != null) {
|
|
board.removeChild(board.lastChild);
|
|
}
|
|
|
|
for (var i=0; i<numMines; i++) {
|
|
var index = Math.round(Math.random()*(numDown*numAcross));
|
|
if ((index >= (numDown*numAcross)) ||
|
|
(boardArray[index]!=0)) {
|
|
i--;
|
|
} else {
|
|
boardArray[index] = -1;
|
|
}
|
|
}
|
|
|
|
for(var y=0; y<numDown; y++) {
|
|
|
|
var coverRow = document.createElementNS(svgNS, "g");
|
|
var boardRow = document.createElementNS(svgNS, "g");
|
|
|
|
var sum=0;
|
|
for (y1=y-1; y1<=y+1; y1++) {
|
|
if ((y1 >= 0) &&
|
|
(y1 < numDown) &&
|
|
(boardArray[y1*numAcross] == -1))
|
|
sum++;
|
|
}
|
|
|
|
for(var x=0; x<numAcross; x++) {
|
|
if (x-2 >= 0) {
|
|
for (y1=y-1; y1<=y+1; y1++) {
|
|
if ((y1 >= 0) &&
|
|
(y1 < numDown) &&
|
|
(boardArray[x-2+y1*numAcross] == -1))
|
|
sum--;
|
|
}
|
|
}
|
|
if (x+1 < numAcross) {
|
|
for (y1=y-1; y1<=y+1; y1++) {
|
|
if ((y1 >= 0) &&
|
|
(y1 < numDown) &&
|
|
(boardArray[x+1+y1*numAcross] == -1))
|
|
sum++;
|
|
}
|
|
}
|
|
|
|
if (boardArray[x+y*numAcross] == 0)
|
|
boardArray[x+y*numAcross] = sum;
|
|
|
|
var square = document.createElementNS(svgNS, "use");
|
|
square.setAttributeNS(null, "x", ""+(x*10));
|
|
square.setAttributeNS(null, "y", ""+(y*10));
|
|
square.setAttributeNS(null, "onclick",
|
|
"handleClick(evt, "+x+","+y+")");
|
|
|
|
var cov = square.cloneNode(true);
|
|
cov.setAttributeNS(null, "id", "cover"+x+"-"+y);
|
|
cov.setAttributeNS(xlinkNS, "href", "#blank");
|
|
var g = document.createElementNS(svgNS, "g");
|
|
g.appendChild(cov);
|
|
coverRow.appendChild(g);
|
|
|
|
square.setAttributeNS(null, "id", "square"+x+"-"+y);
|
|
if (boardArray[x+y*numAcross] == -1)
|
|
square.setAttributeNS(xlinkNS, "href", "#bomb");
|
|
else
|
|
square.setAttributeNS(xlinkNS, "href", "#square"+sum);
|
|
var g = document.createElementNS(svgNS, "g");
|
|
g.appendChild(square);
|
|
boardRow.appendChild(g);
|
|
}
|
|
cover.appendChild(coverRow);
|
|
board.appendChild(boardRow);
|
|
}
|
|
|
|
updateText("working", "");
|
|
updateText("title", "SVG Mines");
|
|
}
|
|
|
|
function handleClick(evt, x, y) {
|
|
if (isGameOver) return;
|
|
if ((evt.button == 1) ||
|
|
(evt.shiftKey)) {
|
|
placeFlag(x, y);
|
|
}
|
|
else if ((evt.button == 2) ||
|
|
(evt.ctrlKey)) {
|
|
showConnected(x, y);
|
|
}
|
|
else if (evt.button == 0) {
|
|
showSpot(x, y)
|
|
}
|
|
}
|
|
|
|
function placeFlag(x ,y) {
|
|
var idx = x + y*numAcross;
|
|
if (shownArray[idx]) return;
|
|
var elt = document.getElementById("cover"+x+"-"+y);
|
|
var nelt = elt.cloneNode(true);
|
|
if (flagArray[idx]) {
|
|
nelt.setAttributeNS(xlinkNS, "href", "#blank");
|
|
flagArray[idx] = false;
|
|
if (boardArray[idx] == -1) correctFlags--;
|
|
else incorrectFlags--;
|
|
minesLeft++;
|
|
} else {
|
|
nelt.setAttributeNS(xlinkNS, "href", "#flag");
|
|
flagArray[idx] = true;
|
|
if (boardArray[idx] == -1) correctFlags++;
|
|
else incorrectFlags++;
|
|
minesLeft--;
|
|
}
|
|
|
|
elt.parentNode.replaceChild(nelt, elt);
|
|
updateText("mines", "Mines Left: "+minesLeft);
|
|
|
|
if ((correctFlags == numMines) && (incorrectFlags == 0)) {
|
|
youWin();
|
|
}
|
|
}
|
|
|
|
function showSpot(x, y) {
|
|
var idx = x + y*numAcross;
|
|
if (shownArray[idx]) return;
|
|
|
|
var elt = document.getElementById("cover"+x+"-"+y);
|
|
elt.parentNode.parentNode.removeChild(elt.parentNode);
|
|
shownArray[idx] = true;
|
|
|
|
var val = boardArray[idx];
|
|
if (val == -1) {
|
|
gameOver();
|
|
} else if (val == 0) {
|
|
showConnected(x, y);
|
|
}
|
|
}
|
|
|
|
function showConnected(x, y) {
|
|
for (var dy=-1; dy<=1; dy++) {
|
|
if (y+dy < 0) continue;
|
|
if (y+dy >= numDown ) continue;
|
|
for (var dx=-1; dx<=1; dx++) {
|
|
if (x+dx < 0) continue;
|
|
if (x+dx >= numDown ) continue;
|
|
var idx = x+dx + (y+dy)*numAcross;
|
|
if (shownArray[idx]) continue;
|
|
if (flagArray[idx]) continue;
|
|
|
|
var elt = document.getElementById("cover"+(x+dx)+"-"+(y+dy));
|
|
elt.parentNode.parentNode.removeChild(elt.parentNode);
|
|
shownArray[idx] = true;
|
|
|
|
var val = boardArray[idx];
|
|
if (val == -1) {
|
|
gameOver();
|
|
} else if (val == 0) {
|
|
showConnected(x+dx, y+dy);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function gameOver() {
|
|
isGameOver=true;
|
|
updateText("title", "Game Over");
|
|
showBoard();
|
|
}
|
|
|
|
function showBoard() {
|
|
while (cover.lastChild != null) {
|
|
cover.removeChild(cover.lastChild);
|
|
}
|
|
var nc = numAcross*numDown;
|
|
for (var i=0; i<nc; i++)
|
|
shownArray[i] = true;
|
|
}
|
|
|
|
function youWin() {
|
|
isGameOver=true;
|
|
updateText("title", "You Win");
|
|
}
|
|
|
|
function updateText(id, lbl) {
|
|
var elt = document.getElementById(id);
|
|
var grp = elt.parentNode;
|
|
var newelt = elt.cloneNode(true);
|
|
|
|
if (newelt.firstChild == null) {
|
|
newelt.appendChild(document.createTextNode(lbl));
|
|
} else {
|
|
newelt.replaceChild(document.createTextNode(lbl), newelt.firstChild);
|
|
}
|
|
grp.replaceChild(newelt, elt);
|
|
}
|
|
|
|
function largerBoard(evt) {
|
|
if (boardSize == 1) return;
|
|
boardSize++;
|
|
if (boardSize == 1) {
|
|
numAcross = 16;
|
|
numDown = 16;
|
|
numMines = mines1;
|
|
}
|
|
else if (boardSize == 2) {
|
|
numAcross = 30;
|
|
numDown = 16;
|
|
numMines = mines2;
|
|
}
|
|
updateText("boardsz", "Board Size: "+numAcross+"x"+numDown);
|
|
updateText("title", "");
|
|
updateText("working", "Working");
|
|
setTimeout("initBoard()", 50);
|
|
}
|
|
|
|
function smallerBoard(evt) {
|
|
if (boardSize == 0) return;
|
|
boardSize--;
|
|
if (boardSize == 0) {
|
|
numAcross = 8;
|
|
numDown = 8;
|
|
numMines = mines0;
|
|
}
|
|
else if (boardSize == 1) {
|
|
numAcross = 16;
|
|
numDown = 16;
|
|
numMines = mines1;
|
|
}
|
|
updateText("boardsz", "Board Size: "+numAcross+"x"+numDown);
|
|
updateText("title", "");
|
|
updateText("working", "Working");
|
|
setTimeout("initBoard()", 50);
|
|
}
|
|
|
|
function newGame(evt) {
|
|
updateText("title", "");
|
|
updateText("working", "Working");
|
|
setTimeout("initBoard()", 50);
|
|
}
|
|
|
|
]]>
|
|
</script>
|
|
|
|
<defs>
|
|
<radialGradient id="bombGrad" gradientUnits="userSpaceOnUse"
|
|
cx="5" cy="6.5" fx="4" fy="5" r="2.5">
|
|
<stop offset="0%" stop-color="#FFF"/>
|
|
<stop offset="20%" stop-color="#888"/>
|
|
<stop offset="100%" stop-color="#000"/>
|
|
</radialGradient>
|
|
<path id="empty" style="fill:#AAA; stroke:#DDD; stroke-width:0.5;"
|
|
d="M0.25,0.25 h9.5 v9.5 h-9.5 v-9.5"/>
|
|
|
|
<g id="blank"
|
|
><rect style="fill:#AAA" width="10" height="10"
|
|
/><path style="fill:#DDD"
|
|
d="M0,0 h10 l-1,1 h-8 v8 l-1,1 v-10"
|
|
/><path style="fill:#888"
|
|
d="M10,10 h-10 l1,-1 h8 v-8 l1,-1 v10"
|
|
/></g>
|
|
|
|
<use id="square0" xlink:href="#empty"/>
|
|
<g id="square1" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#008" pointer-events="none">1</text></g>
|
|
<g id="square2" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#00C" pointer-events="none">2</text></g>
|
|
<g id="square3" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#40F" pointer-events="none">3</text></g>
|
|
<g id="square4" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#80C" pointer-events="none">4</text></g>
|
|
<g id="square5" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#C0C" pointer-events="none">5</text></g>
|
|
<g id="square6" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#F08" pointer-events="none">6</text></g>
|
|
<g id="square7" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#F04" pointer-events="none">7</text></g>
|
|
<g id="square8" style="text-anchor:middle; font-size:8;"
|
|
><use xlink:href="#empty"
|
|
/><text x="5" y="8" fill="#F00" pointer-events="none">8</text></g>
|
|
|
|
<g id="bomb"
|
|
><use xlink:href="#empty"
|
|
/><rect fill="#000" x="4" y="3" width="2" height="2"
|
|
/><circle fill="url(#bombGrad)" cx="5" cy="6.5" r="2.5"
|
|
/><path fill="none" stroke="#000" stroke-width="0.3"
|
|
d="M5,3 c0,-1.5 1.5,-1.5 1.5,0 c0,1.5 1.5,1.5 1.5,0"
|
|
/></g>
|
|
|
|
<g id="flag"
|
|
><use xlink:href="#blank"
|
|
/><path d="M3.5,2 h.5 v6.5 h-1 l.5,-6.5"
|
|
/><path fill="crimson" d="M4,2 l4,1.5 l-4,1.5 z"
|
|
/></g>
|
|
</defs>
|
|
|
|
<g id="body">
|
|
<text id="title" x="25" y="60" font-size="40"
|
|
pointer-events="none">SVG Mines</text>
|
|
<text id="mines" x="250" y="30" font-size="20"
|
|
pointer-events="none">Mines Left: </text>
|
|
|
|
<text id="boardsz" x="250" y="54" font-size="20"
|
|
pointer-events="none">Board Size: </text>
|
|
<g transform="translate(242, 38)" fill="black">
|
|
<path onclick="largerBoard(evt)"
|
|
d="M2.5,0 l-2.5,7 h5 z"/>
|
|
<path onclick="smallerBoard(evt)"
|
|
d="M0,9 h5 l-2.5,7 z"/>
|
|
</g>
|
|
|
|
<g text-anchor="middle" >
|
|
<g id="help" >
|
|
<desc xml:space="preserve"
|
|
>Left: show
|
|
Right or Shift: place flag
|
|
Middle or Control: show surround</desc>
|
|
<circle cx="430" cy="18" r="12"
|
|
fill="grey" stroke="lightgrey" stroke-width="2" />
|
|
<text font-size="15" fill="blue" x="430" y="25"
|
|
pointer-events="none">?</text>
|
|
</g>
|
|
|
|
<g onclick="newGame()">
|
|
<desc xml:space="preserve">Start new game</desc>
|
|
<circle cx="430" cy="48" r="12"
|
|
fill="grey" stroke="lightgrey" stroke-width="2" />
|
|
<text font-size="10" fill="blue" x="430" y="53"
|
|
pointer-events="none">NG</text>
|
|
</g>
|
|
</g>
|
|
|
|
<g id="field" transform="translate(25,75) scale(2)"
|
|
onload="initBoard(evt)">
|
|
<g id="board">
|
|
</g>
|
|
|
|
<g id="cover">
|
|
</g>
|
|
</g>
|
|
<text id="working" fill="green" x="25" y="60" font-size="40"
|
|
pointer-events="none">Working</text>
|
|
</g>
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Batik sample mark -->
|
|
<!-- ============================================================= -->
|
|
<use xlink:href="batikLogo.svg#Batik_Tag_Box" />
|
|
</svg>
|