[JavaScript前端开发及实例教程]计算器井字棋游戏的实现
计算器(网页内实现效果)
HTML部分
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Calculator</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section>
<div class="container">
<div id="display"></div>
<div class="buttons">
<div class="button">C</div>
<div class="button">/</div>
<div class="button">*</div>
<div class="button">←</div>
<div class="button">7</div>
<div class="button">8</div>
<div class="button">9</div>
<div class="button">-</div>
<div class="button">4</div>
<div class="button">5</div>
<div class="button">6</div>
<div class="button">+</div>
<div class="button">1</div>
<div class="button">2</div>
<div class="button">3</div>
<div class="button">.</div>
<div class="button">(</div>
<div class="button">0</div>
<div class="button">)</div>
<div id="equal" class="button">=</div>
</div>
</div>
</section>
<script src="index.js"></script>
</body>
</html>
CSS部分
.container {
max-width: 400px;
margin: 10vh auto 0 auto;
box-shadow: 0px 0px 43px 17px rgba(153,153,153,1);
}
#display {
text-align: right;
height: 70px;
line-height: 70px;
padding: 16px 8px;
font-size: 25px;
}
.buttons {
display: grid;
border-bottom: 1px solid #999;
border-left: 1px solid#999;
grid-template-columns: 1fr 1fr 1fr 1fr;
}
.buttons > div {
border-top: 1px solid #999;
border-right: 1px solid#999;
}
.button {
border: 0.5px solid #999;
line-height: 100px;
text-align: center;
font-size: 25px;
cursor: pointer;
}
#equal {
background-color: rgb(85, 85, 255);
color: white;
}
.button:hover {
background-color: #323330;
color: white;
transition: 0.5s ease-in-out;
}
JavaScript部分
//思路:
//1.用map或者forEach或者for循环给每个按钮(button)加上一个事件监听器addEventListener()
//2.当点击c的时候归零
//3.当点击=的时候把display里的值进行计算,可以用eval函数
//4.当点击<-时候,减去一个数
//5.当点击其他按钮的时候,就是把数往display里面加
//6.你可以用switch case来运行以上的不同情况按键,用if else也可以
// Get the display element
var display = document.getElementById('display');
// Get all the buttons
var buttons = Array.from(document.getElementsByClassName('button'));
// Add click event listener to each button
buttons.forEach(function(button) {
button.addEventListener('click', function() {
handleButtonClick(button.textContent);
});
});
// Function to handle button clicks
function handleButtonClick(value) {
switch (value) {
case 'C':
// Clear the display
display.textContent = '';
break;
case '=':
try {
// Evaluate the expression in the display using eval
display.textContent = eval(display.textContent);
} catch (error) {
// Handle errors, e.g., division by zero
display.textContent = 'Error';
}
break;
case '←':
// Remove the last character from the display
display.textContent = display.textContent.slice(0, -1);
break;
default:
// Append the clicked button value to the display
display.textContent += value;
break;
}
}
井字棋
HTML部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>三连棋</title>
<link href="index.css" rel="stylesheet" />
</head>
<body>
<h1>三连棋</h1>
<div id="board">
<!-- 棋盘上每个格子我们管它叫tile,并且自定义一个属性叫data-index,方便计数-->
<!-- right-border就是棋盘内部的边框,给border上颜色 -->
<div data-index="1" class="tile right-border bottom-border"></div>
<div data-index="2" class="tile right-border bottom-border"></div>
<div data-index="3" class="tile bottom-border"></div>
<div data-index="4" class="tile right-border bottom-border"></div>
<div data-index="5" class="tile right-border bottom-border"></div>
<div data-index="6" class="tile bottom-border"></div>
<div data-index="7" class="tile right-border"></div>
<div data-index="8" class="tile right-border"></div>
<div data-index="9" class="tile"></div>
<!-- 三个棋子连到一起会出现一条红色线,我们管这个红色线叫strike -->
<div id="strike" class="strike"></div>
</div>
<div id="game-over-area" class="hidden">
<h2 id="game-over-text">获胜的是 X</h2>
<button id="play-again">Play Again</button>
</div>
<script src="index.js"></script>
</body>
</html>
CSS部分
/* 整体的棋盘 */
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: black;
color: greenyellow;
}
/* 把1-9的数字,分成三列 */
#board {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
/* 鼠标移动到格子里就变成一个手掌图标 */
cursor: pointer;
position: relative;
}
/* 每个格子 */
.tile {
color: currentColor;/*currentColor继承于body里面的color*/
font-size: 2em;
display: flex;
justify-content: center;
align-items: center;
}
/* 给格子边框上颜色 */
.right-border {
border-right: 0.2em solid indigo;
}
/* 给格子边框上颜色 */
.bottom-border {
border-bottom: 0.2em solid indigo;
}
/* 三个棋子连到一起会出现一条红色线,我们管这个红色线叫strike */
.strike {
position: absolute;
background-color: darkred;
}
/* 三个棋子在第1行连成一条线 */
.strike-row-1 {
width: 100%;
height: 4px;
top: 15%;
}
/* 三个棋子在第2行连成一条线 */
.strike-row-2 {
width: 100%;
height: 4px;
top: 48%;
}
/* 三个棋子在第3行连成一条线 */
.strike-row-3 {
width: 100%;
height: 4px;
top: 83%;
}
/* 三个棋子在第1列连成一条线 */
.strike-column-1 {
height: 100%;
width: 4px;
left: 15%;
}
/* 三个棋子在第2列连成一条线 */
.strike-column-2 {
height: 100%;
width: 4px;
left: 48%;
}
/* 三个棋子在第3列连成一条线 */
.strike-column-3 {
height: 100%;
width: 4px;
left: 83%;
}
/* 三个棋子在斜对角连成一条线 */
.strike-diagonal-1 {
width: 90%;
height: 4px;
top: 50%;
left: 5%;
transform: skewY(45deg); /* skewy可以改变线的角度 */
}
.strike-diagonal-2 {
width: 90%;
height: 4px;
top: 50%;
left: 5%;
transform: skewY(-45deg);
}
h1 {
color: currentColor;
}
#game-over-area {
text-align: center;
border: indigo 8px solid;
padding: 50px;
width: 50%;
margin-top: 50px;
}
h2 {
color: currentColor;
font-size: 2em;
margin-top: 0px;
}
/* 重玩的按钮 */
button {
background-color: transparent;
color: currentColor;
border: currentColor 1px solid;
padding: 10px;
font-size: 1.5em;
}
/* play again区域在游戏结束前不显示 */
.hidden {
display: none;
}
/* play again区域在游戏结束后显示 */
.visible {
display: block;
}
/* 玩家1点一下棋盘显示X */
.x-hover:hover::after {
content: "X";
opacity: 0.4;
}
/* 玩家2点一下棋盘显示O */
.o-hover:hover::after {
content: "O";
opacity: 0.4;
}
JavaScript部分
//选中所有的格子tile
var tiles = document.querySelectorAll(".tile");
//玩家X
var PLAYER_X = "X";
//玩家O
var PLAYER_O = "O";
//玩家X先下,之后这个变量turn会切换成另外一个玩家
var turn = PLAYER_X;
//boardstate追踪棋盘上的情况,把每一步下的棋放在对应下标放进数组。Array(tiles.length)就是9个格子
var boardState = Array(tiles.length);
boardState.fill(null);
//获取棋盘上的一些元素
var strike = document.getElementById("strike");
var gameOverArea = document.getElementById("game-over-area");
var gameOverText = document.getElementById("game-over-text");
var playAgain = document.getElementById("play-again");
//重新开始 play again
playAgain.addEventListener("click", startNewGame);
//音效
var gameOverSound = new Audio("sounds/game_over.wav");
var clickSound = new Audio("sounds/click.wav");
//用forEach给每一个格子增加addEventListener,当玩家点击这个格子的时候,
//你需要执行一个tileClick函数(在37行),tileClick函数的作用是显示X 或者 O
//*******************请写代码完成上述功能*******************
tiles.forEach(function (tile) {
tile.addEventListener("click", tileClick);
});
//event参数是玩家点击的方块
//*******************请写代码完成上述功能*******************
function tileClick(event) {
//如果游戏已经结束了,那就return,停止
if (gameOverArea.classList.contains("visible")) {
return;
}
var clickedTile = event.target;
var tileIndex = parseInt(clickedTile.dataset.index) - 1;
if (boardState[tileIndex] !== null) {
return;
}
if (turn === PLAYER_X) {
clickedTile.innerText = PLAYER_X;
boardState[tileIndex] = PLAYER_X;
turn = PLAYER_O;
} else {
clickedTile.innerText = PLAYER_O;
boardState[tileIndex] = PLAYER_O;
turn = PLAYER_X;
}
//获取玩家点击的方块
//*******************请写代码完成上述功能*******************
//获取方块的编号:tile.dataset.index是获取data-index自定义属性内容的固定写法
//*******************请写代码完成上述功能*******************
//查看方块内是否已经被玩家点击过了
//*******************请写代码完成上述功能*******************
//如果这一轮是X玩家,那么给这个点击方块里写上X,如果是玩家O,那就给这个点击方块里写上0
//一个玩家落子后,需要切换玩家
//*******************请写代码完成上述功能*******************
//播放点击音效
clickSound.play();
//显示悬浮的文字O或者X
setHoverText();
//查看谁胜了
checkWinner();
}
//当玩家X鼠标移动在方框上时候,显示X;玩家O显示o
function setHoverText() {
//移除所有hover 文字
tiles.forEach(function (tile) {
tile.classList.remove("x-hover");
tile.classList.remove("o-hover");
});
var hoverClass = "".concat(turn.toLowerCase(), "-hover");
tiles.forEach(function (tile) {
if (tile.innerText == "") {
tile.classList.add(hoverClass);
}
});
}
setHoverText();
//查看谁胜利了
function checkWinner() {
//*********************给以下每一行代码添加注释~注释到return那一行*********************
for (var _i = 0, _winningCombinations = winningCombinations; _i < _winningCombinations.length; _i++) {
var winningCombination = _winningCombinations[_i];
// console.log(boardState)
var combo = winningCombination.combo,
strikeClass = winningCombination.strikeClass;
var tileValue1 = boardState[combo[0] - 1];
var tileValue2 = boardState[combo[1] - 1];
var tileValue3 = boardState[combo[2] - 1];
if (tileValue1 != null && tileValue1 === tileValue2 && tileValue1 === tileValue3) {
strike.classList.add(strikeClass);
gameOverScreen(tileValue1);
return;
}
}
//查看平局
var allTileFilledIn = boardState.every(function (tile) {
return tile !== null;
});
if (allTileFilledIn) {
gameOverScreen(null);
}
}
//game over的框
function gameOverScreen(winnerText) {
gameOverArea.classList.remove("hidden");
gameOverText.innerText = winnerText ? `Player ${winnerText} wins!` : "平局!";
//把game over的框显示出来
//*******************请写代码完成上述功能*******************
}
//重新开始一局游戏
function startNewGame() {
strike.className = "strike";
gameOverArea.className = "hidden";
boardState.fill(null);
tiles.forEach(function (tile) {
return (tile.innerText = "");
});
turn = PLAYER_X;
setHoverText();
}
//所有胜利组合
var winningCombinations = [
//例如
{ combo: [1, 2, 3], strikeClass: "strike-row-1" },
{ combo: [4, 5, 6], strikeClass: "strike-row-2" },
{ combo: [7, 8, 9], strikeClass: "strike-row-3" },
{ combo: [1, 4, 7], strikeClass: "strike-col-1" },
{ combo: [2, 5, 8], strikeClass: "strike-col-2" },
{ combo: [3, 6, 9], strikeClass: "strike-col-3" },
{ combo: [1, 5, 9], strikeClass: "strike-diagonal-1" },
{ combo: [3, 5, 7], strikeClass: "strike-diagonal-2" },
//建立一个对象,把所有胜利组合都放进去,上面只是一个例子,一共有8个组合,你还要写7个组合
//*******************请写代码完成上述功能*******************
];