首页 > 解决方案 > 如何在纯JS中单击的单元格上绘制符号

问题描述

从昨天开始,我一直在集思广益,尝试了很多,但是当我单击特定单元格时,无法弄清楚如何在板上绘制 X,它总是在第一个单元格上绘制它。我认为如果我将 calculatePos 函数中的 newRow 和 newCol 作为参数传递给 drawSymbol 函数中的 ctx.lineTo 可以解决,但我不确定如何访问它?
HTML

<!DOCTYPE="html5">
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <link rel="stylesheet" href="tic-tac-toe.css">
    <title>TIC TAC TOE IN JS</title>
    <h1 class='header'>TIC TAC TOE in JS</h1>
  </head>
<body>
    <div class='canvas'>
        <canvas id="canvas" width='300px' height="300px"></canvas>
    </div>
    <div class='scores'>
        <div>Player 1 Wins: <span id="score-x">0</span></div>
        <div>Ties: <span id="score-tie">0</span> </div>
        <div>Player 2 Wins: <span id="score-o">0</span> </div>
    </div>

<script src="./tictactoe.js"></script>

</body>

JS

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

//Variables
let row = 3;
let col = 3;
const vacant = "white";
let sq = 100;
let w = canvas.clientWidth/3;
let h = canvas.clientHeight/3;
let currentPlayer = "";

//players
const players = ['X', 'O']
const player1 = players[0];
const player2 = players[1];


//draw a square
function drawSquare(x, y, color) {
    ctx.fillStyle = color;
    ctx.fillRect(x*sq, y*sq, sq, sq);
    ctx.strokeStyle = 'black';
    ctx.strokeRect(x*sq, y*sq, sq, sq);
}

//Create board
let board = [ ];
for(let r = 0; r < row; r++){
    board[r] = [ ];
        for(let c = 0; c < col; c++) {
            board[r][c] = vacant;
        }
}
//Draw Board
function drawBoard() {
    for(r = 0; r < row; r++) {
        for(c = 0; c < col; c++){
            drawSquare(c, r, board[r][c]);
        }
    }
}
drawBoard();



// sets up the game
function setup() {

    //let the starting player be selected at random
    let randomPlayer = Math.floor(Math.random() *2 );
    if (randomPlayer == 0){
        currentPlayer = player1;
        alert('Player 1 starts the game !')
    }else {
        currentPlayer = player2;
        alert('Player 2 starts the game !')
    };





    function calculatePos () {
        // checks for click position
        canvas.addEventListener('click', event => {

            // get the position of the board relative to the page
            let {left, top} = canvas.getBoundingClientRect();

            // get the position of the click relative to the page
            let mouseX = event.clientX - left;
            let mouseY = event.clientY - top;

            // calculate which square is being clicked 
            let newRow = Math.floor(mouseY / sq);
            let newCol = Math.floor(mouseX / sq); 
            return(newRow, newCol)
        })  
    }
        // listens for clicks on the canvas to draw the symbol
        function drawSymbol (newRow, newCol) {
            let xr = w*0.95;
            if(currentPlayer == players[0]) {
                canvas.addEventListener('click', () => {
                    ctx.lineWidth = 5;
                    ctx.strokeStyle = 'black';
                    ctx.beginPath();
                    ctx.moveTo(newRow, newCol);
                    ctx.lineTo(newRow+xr,newCol+xr);
                    ctx.stroke();
                    ctx.beginPath();
                    ctx.moveTo(newRow+xr, newCol);
                    ctx.lineTo(newRow,newCol+xr);
                    ctx.stroke();
            }) 
            } else {
                    canvas.addEventListener('click', () => {
                        ctx.lineWidth = 5;
                        ctx.strokeStyle = 'black';
                        ctx.beginPath();
                        ctx.arc(col + (xr * 1.8), row + (xr * 1.8), 40, 0, 2 * Math.PI); // needs to be updated, don't worry about that
                        ctx.stroke();
            }
        )}
        }
        drawSymbol(row, col);



calculatePos();
}
setup();

标签: javascriptcanvasdrawing

解决方案


这是一种使用文本的方法,strokeText我认为这种方法更容易

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = "white";
ctx.font = "80px monospace";

let row = col = 3;
let sq = 100;

function drawBoard() {
  for (r = 0; r < row; r++) {
    for (c = 0; c < col; c++) {
      ctx.fillRect(r * sq, c * sq, sq, sq);
      ctx.strokeRect(r * sq, c * sq, sq, sq);
    }
  }
}

function drawSymbol(event) {
  let rect = canvas.getBoundingClientRect();
  let row = Math.floor((event.clientX - rect.left) / sq);
  let col = Math.floor((event.clientY - rect.top) / sq);
  let text = Math.random() > 0.5 ? "O" : "X";

  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.strokeText(text, row * sq + 25, col * sq + 80);
  ctx.stroke();
}

canvas.addEventListener('click', drawSymbol, false)
drawBoard();
<body>
  <div class='canvas'>
    <canvas id="canvas" width='300px' height="300px"></canvas>
  </div>
</body>

当您为某个问题发布代码时,您必须首先将您的代码简化为一个最小的示例,像您提出的那样一个巨大的问题会阻止许多人甚至看它。


推荐阅读