使用 jQuery 的两人井字游戏 2D 游戏
使用 jQuery 的两人井字游戏 2D 游戏。
引言
井字棋是一款非常简单的纸笔游戏。在这个例子中,我展示了如何使用 jQuery 在 HTML 上构建一个 2D 井字棋游戏。
背景
井字棋是关于 O 和 X 的。游戏规则非常简单。在一个 3x3 的网格上,玩家必须水平/垂直/对角线连接 3 个连续的 O 或 X。我设计了一个非常简单的界面,并使用 jQuery 来实现游戏玩法。在下一节中,我将解释代码。
Using the Code
在这里,我将解释代码块。
<!DOCTYPE html>
<html>
<head>
<title>TicTacToe</title>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<div id="game-wrap">
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
</div>
<div id="panel">
<input type="text" id="player-1-inp" placeholder="Enter player 1">
<input type="text" id="player-2-inp" placeholder="Enter player 2">
<button id="playButton">Play!</button>
<h1 id="board"></h1>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
在这里,我使用简单的 HTML div
创建了一个 3x3 的网格。我使用了三个行 div
,并在每个行 div
中使用了三个列 div
。我将行和列的名称保持相同,因为我计划稍后将此结构用作 2D 网格。在网格下方,我放置了一个面板 div
,玩家可以在其中设置他们的名字、开始游戏并查看游戏状态消息。
body{
background: #323232;
}
#game-wrap{
width: 450px;
height: 455px;
margin: 0 auto;
background: gray;
margin-top: 50px;
border-left: 5px solid gray;
border-top-right-radius: 20px;
border-top-left-radius: 20px;
}
.row{
width: 100%;
height: 150px;
}
.col{
width: 32%;
height: 145.5px;
border: 3px solid white;
float: left;
text-align: center;
font-size: 150px;
font-family: helvetica;
color: white;
cursor: pointer;
}
.matched{
color: maroon;
}
.player-1-color{
color: maroon;
}
.col:nth-child(1){
border-left: none;
}
.col:nth-child(3){
border-right: none;
}
.row:nth-child(1) .col{
border-top: none;
margin-top: 3px;
}
.row:nth-child(3) .col{
border-bottom: none;
margin-bottom: 3px;
}
#panel{
width: 435px;
padding: 10px;
margin: 0 auto;
background: brown;
border-bottom-right-radius: 20px;
border-bottom-left-radius: 20px;
}
#board{
font-size: 30px;
font-family: helvetica;
color: whitesmoke;
margin-top: 10px;
}
这是游戏的 CSS 设计。代码不言自明。我假设使用 jQuery 的人都了解 CSS。
jQuery 部分
在这一部分,我将分别编写多个代码块,并单独解释它们。但它们都来自同一个 .js 文件。起初,我们需要创建一些函数并进行一些初始化,然后才能进入主要的游戏玩法。
var player1Name="" , player2Name="", turn = "";
var grid = [[0,0,0],[0,0,0],[0,0,0]];
var hasWinner = 0, moveCount=0;
function boardMsg(x){
return $("#board").text(x);
}
在这里,我们为玩家姓名、跟踪游戏回合、一个 3x3 数组来映射玩家的移动、用于查找获胜者的标志变量、用于计算总移动次数的标志变量(最大 moveCount
将是 9
)以及最后用于在面板上写入的函数创建了一些新变量。
function setTurn(){
var r = Math.floor((Math.random() * 2) + 1);
hasWinner=0;
if(r==1){
turn = player1Name;
boardMsg(player1Name+"'s turn now!");
}
else{
turn = player2Name;
boardMsg(player2Name+"'s turn now!");
}
}
然后,我们编写一个函数来随机设置玩家的回合。因为我们不想每次都让某个玩家先走。使用随机数,我们设置了回合,并将获胜者标志设置为 0
,因为游戏刚刚开始。
function init(){
turn = "";
grid = [[0,0,0],[0,0,0],[0,0,0]];
boardMsg("");
$(".col").map(function() {
$(this).text("");
}).get();
hasWinner = 0;
moveCount=0;
}
现在,我们需要编写一个初始化函数,如下所示,因为如果游戏已经玩了一次或多次,每次玩家重玩时,都需要清除旧值,例如回合、网格数组、面板消息、网格的 O/X 以及标志。
$("#playButton").click(function (){
if(hasWinner==1){
init();
}
player1Name = $("#player-1-inp").val();
player2Name = $("#player-2-inp").val();
if(player1Name=="" || player2Name==""){
alert("Please set player all the names.");
return;
}
setTurn();
});
这个函数是播放按钮的点击事件,用于从输入标签获取玩家的值。如果之前有获胜者,则表示此点击是用于“再玩一次”按钮。因此,我们重新初始化必要的值。然后,我们将检查玩家是否设置了他们的名字。最后,我们设置回合。
$(".col").click(function (){
if(player1Name=="" || player2Name==""){
alert("Please set player all the names.");
return;
}
var row = $(this).parent().index();
var col = $(this).index();
if(grid[row][col]!==0){
alert("This position is taken. Please try other position.");
return;
}
if(hasWinner==1){
alert("Please click play again");
return;
}
if(turn==player1Name){
moveCount++;
$(this).text("O");
grid[row][col] = 1;
var ifWon = winnerCheck(1,player1Name);
if(!ifWon){
if(moveCount>=9){
boardMsg("Match Drawn!");
moveCount=0;
$("#playButton").text("Play again");
hasWinner=1;
return;
}else{
turn = player2Name;
boardMsg(player2Name+"'s turn now!");
}
return;
}
else{
return;
}
}
else if(turn==player2Name){
moveCount++;
$(this).text("X");
grid[row][col] = 2;
var ifWon = winnerCheck(2,player2Name);
if(!ifWon){
if(moveCount>=9){
boardMsg("Match Drawn!");
moveCount=0;
$("#playButton").text("Play again");
hasWinner=1;
return;
}else{
turn = player1Name;
boardMsg(player1Name+"'s turn now!");
}
return;
}
else{
return;
}
}
});
这是网格单元的点击事件。在这里,我们在每个 .col
类上使用 jQuery 类选择器点击函数。如果玩家点击任何 .col
div
,我们将有条件地检查当前是谁在玩。第一个条件是针对 player1
。然后,我们使用 jQuery 的 index()
和 parent()
获取网格单元的行-列位置。如果该位置已被占用,我们将继续进行。或者,我们将检查回合以确定哪个玩家正在玩。检查完回合后,我们将增加移动计数,因为这是一次成功的移动。然后,我们将 1 放入网格的 [row][col] 位置,而玩家刚刚点击了实际网格的 [row][col] 位置。我们将 1 和玩家姓名传递给即将到来的获胜者检查函数。如果玩家没有获胜,我们将检查是否已用尽移动次数且游戏是否已平局。如果是平局,我们将向面板发送消息并更改标志值。在这里,尽管游戏是平局,但我将 1 设置为 hasWinner
标志,因为在 setTurn
函数中,如果需要创建新游戏,我们需要传递 init()
的条件。然后,如果不是平局,我们将回合交给第二个玩家,并向面板发送消息。并且在平局的条件下,如果玩家获胜,则什么都不会发生,只会停止函数。因此,请仔细检查我为两个玩家写了两个 if
条件。在这些条件内部,除了某些值之外,一切都相同,例如当条件是为玩家 1 时,我们将 1 放入网格,将 1 和玩家 1 的姓名传递给获胜者检查函数,并将回合交给玩家 2。对于玩家 2,所有这些事情都将相反。
function winnerCheck(n,playerName){
if(
(grid[0][0]==n && grid[0][1]==n && grid[0][2]==n) ||
(grid[1][0]==n && grid[1][1]==n && grid[1][2]==n) ||
(grid[2][0]==n && grid[2][1]==n && grid[2][2]==n) ||
(grid[0][0]==n && grid[1][0]==n && grid[2][0]==n) ||
(grid[0][1]==n && grid[1][1]==n && grid[2][1]==n) ||
(grid[0][2]==n && grid[1][2]==n && grid[2][2]==n) ||
(grid[0][0]==n && grid[1][1]==n && grid[2][2]==n)||
(grid[0][2]==n && grid[1][1]==n && grid[2][0]==n)
){
boardMsg(playerName+" won the game!");
hasWinner = 1;
moveCount=0;
$("#playButton").text("Play again");
return true;
}
return false;
}
最后一个函数是检查获胜者。在这个函数中,我们传递了一个数字和玩家姓名作为参数。然后我们检查网格上水平/垂直/对角线是否有三个连续的 n
。如果其中任何一个条件匹配,则该玩家赢得了比赛。因此,当我们将 1 和玩家 1 的姓名传递给函数时,它将检查玩家 1 是否赢得了比赛,而当我们传递 2 和玩家 2 的姓名时,它将检查玩家 2 是否赢得了比赛。然后我们向面板发送消息并更新标志。因为 UI 现在应该停止游戏。然后,我们将按钮的文本更改为“再玩一次”。最后,我们返回 true
。如果所有 8 个条件都为 false
,我们则返回 false
。根据返回值,网格单元的点击函数将按我之前解释的那样工作。
在 jsfiddle 上玩这个游戏。