十七、第十四章的最终代码
清单 C-1 指定了第十四章中项目的最终代码。这可以从下载源的Checkers.cshtml
文件中获得。我把它放在这里,以防你不下载代码就想看。
Listing C-1. Chapter 14 Final Code
<head>
<style type="text/css" >
.board
{
width: 400px;
height: 400px;
margin-top: 20px;
}
.bblack
{
background-color: #b93030;
border-color: #b93030;
border-width: 1px;
border-style: solid;
width: 48px;
height: 48px;
float: left;
margin: 0px;
padding: 0px;
}
.bwhite
{
background-color: #f7f7f7;
border-color: #b93030;
border-width: 1px;
border-style: solid;
width: 48px;
height: 48px;
float: left;
margin: 0px;
padding: 0px;
}
.piece
{
margin-left: 4px;
margin-top: 4px;
}
.bblack.drop
{
opacity: 0.5;
}
.piece.selected
{
opacity: 0.5;
}
</style>
</head>
<body>
<div class="board">
@for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
string id = x.ToString() + y.ToString();
string css;
if ((x + y) % 2 == 0)
{
css = "bwhite";
}
else
{
css = "bblack";
}
<text>
<div id="@id" class="@css" draggable="false">
@if ((x + y) % 2 != 0 && y != 3 && y != 4)
{
string imgSrc;
string pid;
if (y < 3)
{
imgSrc = "../img/WhitePiece.png";
pid = "w" + id;
}
else
{
imgSrc = "../img/BlackPiece.png";
pid = "b" + id;
}
<text>
<img id="@pid" src="@imgSrc" draggable="true" class="piece">
</text>
}
</div>
</text>
}
}
</div>
<script type="text/javascript">
// Get all the black squares
var squares = document.querySelectorAll('.bblack');
var i = 0;
while (i < squares.length) {
var s = squares[i++];
// Add the event listeners
s.addEventListener('dragover', dragOver, false);
s.addEventListener('drop', drop, false);
s.addEventListener('dragenter', dragEnter, false);
s.addEventListener('dragleave', dragLeave, false);
}
i = 0;
var pieces = document.querySelectorAll('img');
while (i < pieces.length) {
var p = pieces[i++];
p.addEventListener('dragstart', dragStart, false);
p.addEventListener('dragend', dragEnd, false);
}
// Handle the dragover event
function dragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
// Get the img element that is being dragged
var dragID = e.dataTransfer.getData("text");
var dragPiece = document.getElementById(dragID);
// Work around - if we can't get the dataTransfer, don't
// disable the move yet, the drop event will catch this
if (dragPiece) {
if (e.target.tagName === "DIV" &&
isValidMove(dragPiece, e.target, false)) {
e.dataTransfer.dropEffect = "move";
}
else {
e.dataTransfer.dropEffect = "none";
}
}
}
function dragStart(e) {
if (e.target.draggable) {
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text", e.target.id);
e.target.classList.add("selected");
var dragIcon = document.createElement("img");
dragIcon.src = "../img/smiley.jpg";
e.dataTransfer.setDragImage(dragIcon, 0, 0);
}
}
function dragEnd(e) {
e.target.classList.remove("selected");
}
function drop(e) {
// Prevent the event from being raised on the parent element
if (e.stopPropagation) {
e.stopPropagation();
}
// Stop the browsers default action
if (e.preventDefault) {
e.preventDefault();
}
// Get the img element that is being dragged
var droppedID = e.dataTransfer.getData("text");
var droppedPiece = document.getElementById(droppedID);
if (droppedPiece &&
e.target.tagName === "DIV" &&
isValidMove(droppedPiece, e.target, true)) {
// Create a new img on the target location
var newPiece = document.createElement("img");
newPiece.src = droppedPiece.src;
newPiece.id = droppedPiece.id.substr(0, 1) + e.target.id;
newPiece.draggable = droppedPiece.draggable;
if (droppedPiece.draggable) {
newPiece.classList.add("jumpOnly");
}
newPiece.classList.add("piece");
newPiece.addEventListener("dragstart", dragStart, false);
newPiece.addEventListener("dragend", dragEnd, false);
e.target.appendChild(newPiece);
// Remove the previous image
droppedPiece.parentNode.removeChild(droppedPiece);
// Remove the drop effect from the target element
e.target.classList.remove('drop');
// See if the piece needs to be promoted
kingMe(newPiece);
}
}
function dragEnter(e) {
// Get the img element that is being dragged
var dragID = e.dataTransfer.getData("text");
var dragPiece = document.getElementById(dragID);
if (dragPiece &&
e.target.tagName === "DIV" &&
isValidMove(dragPiece, e.target, false)) {
e.target.classList.add('drop');
}
}
function dragLeave(e) {
e.target.classList.remove("drop");
}
function isValidMove(source, target, drop) {
// Get the piece prefix and location
var startPos = source.id.substr(1, 2);
var prefix = source.id.substr(0, 1);
// Get the drop location, strip off the prefix, if any
var endPos = target.id;
if (endPos.length > 2) {
endPos = endPos.substr(1, 2);
}
// You can't drop on the existing location
if (startPos === endPos) {
return false;
}
// You can't drop on occupied square
if (target.childElementCount != 0) {
return false;
}
var jumpOnly = false;
if (source.classList.contains("jumpOnly")) {
jumpOnly = true;
}
// Compute the x and y coordinates
var xStart = parseInt(startPos.substr(0, 1));
var yStart = parseInt(startPos.substr(1, 1));
var xEnd = parseInt(endPos.substr(0, 1));
var yEnd = parseInt(endPos.substr(1, 1));
switch (prefix) {
// For white pieces...
case "w":
if (yEnd <= yStart)
return false; // Can't move backwards
break;
// For black pieces...
case "b":
if (yEnd >= yStart)
return false; // Can't move backwards
break;
}
// These rule apply to all pieces
if (yStart === yEnd || xStart === xEnd)
return false; // Move must be diagonal
if (Math.abs(yEnd - yStart) > 2 || Math.abs(xEnd - xStart) > 2)
return false; // Can't move more than two spaces
if (Math.abs(xEnd - xStart) === 1 && jumpOnly)
return false; // Only jumps are allowed
var jumped = false;
// If moving two spaces, find the square that is jumped
if (Math.abs(xEnd - xStart) === 2) {
var pos = ((xStart + xEnd) / 2).toString() +
((yStart + yEnd) / 2).toString();
var div = document.getElementById(pos);
if (div.childElementCount === 0)
return false; // Can't jump an empty square
var img = div.children[0];
if (img.id.substr(0, 1).toLowerCase() === prefix.toLowerCase())
return false; // Can't jump a piece of the same color
// If this function is called from the drop event
// Remove the jumped piece
if (drop) {
div.removeChild(img);
jumped = true;
}
}
// Set the draggable attribute so the next player can take a turn
if (drop) {
enableNextPlayer(source);
// If we jumped a piece, we're allowed to go again
if (jumped) {
source.draggable = true;
source.classList.add("jumpOnly"); // But only for another jump
}
}
return true;
}
function kingMe(piece) {
// If we're already a king, just return
if (piece.id.substr(0, 1) === "W" || piece.id.substr(0, 1) === "B")
return;
var newPiece;
// If this is a white piece on the 7th row
if (piece.id.substr(0, 1) === "w" && piece.id.substr(2, 1) === "7") {
newPiece = document.createElement("img");
newPiece.src = "../img/WhiteKing.png";
newPiece.id = "W" + piece.id.substr(1, 2);
}
// If this is a black piece on the 0th row
if (piece.id.substr(0, 1) === "b" && piece.id.substr(2, 1) === "0") {
var newPiece = document.createElement("img");
newPiece.src = "../img/BlackKing.png";
newPiece.id = "B" + piece.id.substr(1, 2);
}
// If a new piece was created, set its properties and events
if (newPiece) {
newPiece.draggable = true;
newPiece.classList.add("piece");
newPiece.addEventListener('dragstart', dragStart, false);
newPiece.addEventListener('dragend', dragEnd, false);
var parent = piece.parentNode;
parent.removeChild(piece);
parent.appendChild(newPiece);
}
}
function enableNextPlayer(piece) {
// Get all of the pieces
var pieces = document.querySelectorAll('img');
i = 0;
while (i < pieces.length) {
var p = pieces[i++];
// If this is the same color that just moved, disable dragging
if (p.id.substr(0, 1).toUpperCase() ===
piece.id.substr(0, 1).toUpperCase()) {
p.draggable = false;
}
// Otherwise, enable dragging
else {
p.draggable = true;
}
p.classList.remove("jumpOnly");
}
}
</script>
</body>