首页 > 其他 > 详细

TypeScript实现井字棋小游戏

时间:2020-10-31 16:44:05      阅读:51      评论:0      收藏:0      [点我收藏+]

HTML部分:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Tic Tac Toe</title>
    <link rel="stylesheet" href="style.css" />
</head>

<body>
    <h1>Tic Tac Toe</h1>

    <div class="container">
        <!-- 游戏面板(棋盘) -->
        <div id="bord" class="game-board x">
            <div class="row">
                <div class="cell"></div>
                <div class="cell"></div>
                <div class="cell"></div>
            </div>
            <div class="row">
                <div class="cell"></div>
                <div class="cell"></div>
                <div class="cell"></div>
            </div>
            <div class="row">
                <div class="cell"></div>
                <div class="cell"></div>
                <div class="cell"></div>
            </div>
        </div>

        <!-- 游戏获胜信息面板 -->
        <div id="message" class="game-message">
            <p id="winner">X 赢了!</p>
            <button id="restart">重新开始</button>
        </div>
    </div>
    <script src="./index.js"></script>
</body>

</html>

CSS样式:

p {
  margin: 0;
}

body {
  background-color: #f9f2e7;
}

/* 标题 */
h1 {
  text-align: center;
  font-size: 60px;
  color: #477998;
}

/* 游戏内容容器 */
.container {
  position: relative;
  width: 471px;
  height: 471px;
  margin: 0 auto;
}

/* 游戏获胜信息面板 */
.game-message {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(69, 133, 136, 0.4);
  text-align: center;
}

/* winner 获胜者 */
.game-message p {
  margin: 180px 0 40px 0;
  color: #fff;
  font-size: 50px;
}

/* 重新开始游戏按钮 */
.game-message button {
  color: #517304;
  border-color: #517304;
  width: 110px;
  height: 40px;
  font-size: 20px;
  cursor: pointer;
}

/* 游戏面板棋盘 */
.game-board {
  width: 471px;
  height: 471px;
}
.game-board.x .cell:not(.x):not(.o):hover::before {
  content: ‘X‘;
  color: lightgray;
}
.game-board.o .cell:not(.x):not(.o):hover::before {
  content: ‘O‘;
  color: lightgray;
}

/* 棋盘 - 行 */
.row {
  display: flex;
}
.row:last-child .cell {
  border-bottom: 0;
}

/* 棋盘 - 单元格 */
.cell {
  flex: 1;
  box-sizing: border-box;
  width: 157px;
  height: 157px;
  line-height: 157px;
  border-right: 6px solid #546363;
  border-bottom: 6px solid #546363;
  text-align: center;
  cursor: pointer;
  font-size: 88px;
  font-family: ‘Gill Sans‘, ‘Gill Sans MT‘, Calibri, sans-serif;
}
.cell:last-child {
  border-right: 0;
}

/* x 玩家 */
.cell.x::before {
  content: ‘X‘;
  color: #01a8c6;
}
/* o 玩家 */
.cell.o::before {
  content: ‘O‘;
  color: #8fbe01;
}

ts代码:

enum Player { // 利用枚举来判断值
    X = ‘x‘,
    O = ‘o‘
}
// 判赢数组
let winArr = [
    [0, 1, 2], [3, 4, 5], [6, 7, 8], //
    [0, 3, 6], [1, 4, 7], [2, 5, 8], //
    [0, 4, 8], [2, 4, 6] //
]

let cells = document.querySelectorAll(‘.cell‘); // 获取所有的单元格列表
let gameBord = document.getElementById(‘bord‘)!; // 游戏面板 !是not null 的断言操作符
// 获胜信息面板
let message = document.querySelector(‘#message‘) as HTMLDivElement;
// 获胜者
let winner = document.querySelector(‘#winner‘) as HTMLParagraphElement;
// 重新开始按钮
let restart = document.querySelector(‘#restart‘) as HTMLButtonElement;
//当前玩家
let currentPlayer: Player;

// 记录已下棋的次数
let steps: number;

// 初始化游戏数据, 开始游戏
startGame()

// 重新开始游戏
restart.addEventListener(‘click‘,startGame);

function startGame() {
    // 隐藏获胜信息
    message.style.display = ‘none‘;
    // 重置下棋次数
    steps = 0;
    // 重置默认玩家为 x
    currentPlayer = Player.X
    // 重置下棋提示为 x
    gameBord.classList.remove(Player.X, Player.O);
    gameBord.classList.add(Player.X);
    cells.forEach((item) => {
        let cell  = item as HTMLDivElement;
        // 清空棋盘
        cell.classList.remove(Player.X, Player.O);
        // 移除单元格点击事件、重新给单元格绑定点击事件
        cell.removeEventListener(‘click‘, clickCell);
        cell.addEventListener(‘click‘, clickCell, { once: true })
    })
}

// 棋盘中单元格的click事件处理程序
function clickCell(event: MouseEvent) { // 给当前被点击的单元格添加类名 x
    let target = event.target as HTMLDivElement;
    target.classList.add(currentPlayer); // 每下的一步棋
    steps++;
    // 调用函数判断是否获胜
    let isWin = checkWin(currentPlayer);
    if (isWin) {
        message.style.display = ‘block‘;
        winner.innerText = `${currentPlayer} 赢了`;
        return;
    }

    // 判断平局
    if(steps === 9){
        message.style.display = ‘block‘;
        winner.innerText = `平局`;
        return;
    }

    currentPlayer = currentPlayer === Player.X ? Player.O : Player.X; // 判断下一步提示
    gameBord.classList.remove(Player.X, Player.O); // 移除下一步提示样式
    gameBord.classList.add(currentPlayer); // 根据 currentPlayer 添加 下一步样式
}

// 封装判赢函数
function checkWin(palyer: Player) {
    let isWin = winArr.some((item) => {
        let cellIndex1 = item[0];
        let cellIndex2 = item[1];
        let cellIndex3 = item[2];

        // 判断横、竖、斜是否包含同一类名
        if (
            hasClass(cells[cellIndex1], palyer) &&
            hasClass(cells[cellIndex2], palyer) &&
            hasClass(cells[cellIndex3], palyer) 
            ) {
            return true;
        }
        return false;
    });

    return isWin;
}

// 封装 hasClass 函数 判断 DOM 元素是否包含某个类名;
function hasClass(el: Element, name: string) {
    return el.classList.contains(name);
}

编译后的js:

var Player;
(function (Player) {
    Player["X"] = "x";
    Player["O"] = "o";
})(Player || (Player = {}));
// 判赢数组
var winArr = [
    [0, 1, 2], [3, 4, 5], [6, 7, 8],
    [0, 3, 6], [1, 4, 7], [2, 5, 8],
    [0, 4, 8], [2, 4, 6] //
];
var cells = document.querySelectorAll(‘.cell‘); // 获取所有的单元格列表
var gameBord = document.getElementById(‘bord‘); // 游戏面板 !是not null 的断言操作符
// 获胜信息面板
var message = document.querySelector(‘#message‘);
// 获胜者
var winner = document.querySelector(‘#winner‘);
// 重新开始按钮
var restart = document.querySelector(‘#restart‘);
//当前玩家
var currentPlayer;
// 记录已下棋的次数
var steps;
// 初始化游戏数据, 开始游戏
startGame();
// 重新开始游戏
restart.addEventListener(‘click‘, startGame);
function startGame() {
    // 隐藏获胜信息
    message.style.display = ‘none‘;
    // 重置下棋次数
    steps = 0;
    // 重置默认玩家为 x
    currentPlayer = Player.X;
    // 重置下棋提示为 x
    gameBord.classList.remove(Player.X, Player.O);
    gameBord.classList.add(Player.X);
    cells.forEach(function (item) {
        var cell = item;
        // 清空棋盘
        cell.classList.remove(Player.X, Player.O);
        // 移除单元格点击事件、重新给单元格绑定点击事件
        cell.removeEventListener(‘click‘, clickCell);
        cell.addEventListener(‘click‘, clickCell, { once: true });
    });
}
// 棋盘中单元格的click事件处理程序
function clickCell(event) {
    var target = event.target;
    target.classList.add(currentPlayer); // 每下的一步棋
    steps++;
    // 调用函数判断是否获胜
    var isWin = checkWin(currentPlayer);
    if (isWin) {
        message.style.display = ‘block‘;
        winner.innerText = currentPlayer + " \u8D62\u4E86";
        return;
    }
    // 判断平局
    if (steps === 9) {
        message.style.display = ‘block‘;
        winner.innerText = "\u5E73\u5C40";
        return;
    }
    currentPlayer = currentPlayer === Player.X ? Player.O : Player.X; // 判断下一步提示
    gameBord.classList.remove(Player.X, Player.O); // 移除下一步提示样式
    gameBord.classList.add(currentPlayer); // 根据 currentPlayer 添加 下一步样式
}
// 封装判赢函数
function checkWin(palyer) {
    var isWin = winArr.some(function (item) {
        var cellIndex1 = item[0];
        var cellIndex2 = item[1];
        var cellIndex3 = item[2];
        // 判断横、竖、斜是否包含同一类名
        if (hasClass(cells[cellIndex1], palyer) &&
            hasClass(cells[cellIndex2], palyer) &&
            hasClass(cells[cellIndex3], palyer)) {
            return true;
        }
        return false;
    });
    return isWin;
}
// 封装 hasClass 函数 判断 DOM 元素是否包含某个类名;
function hasClass(el, name) {
    return el.classList.contains(name);
}

 

TypeScript实现井字棋小游戏

原文:https://www.cnblogs.com/brotheryang/p/13905536.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!