首页 > 解决方案 > 如何仅使用 context.save/context.restore、if 语句、画布和动画制作井字游戏?

问题描述

字母 O 字母 X

如何仅使用 context.save/context.restore、if 语句、画布和动画制作井字游戏?我也在努力做到这一点,如果图像 X 显示在框 1 中,图像 O 不能显示在同一个框中,所以你不能作弊。

我不知道如何防止有人将图像 O 放在图像 X 上,反之亦然。请有人告诉我一种方法来防止人们将 O 放在 X 上,反之亦然。

这是我到目前为止所拥有的

<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title></title>
        <link rel="stylesheet" href="U1TS.css">
    </head>
    <body>

        <canvas id="canvas" width="400" height="400"></canvas>
        <br>

        <button onclick="Restart()">Restart</button>
        <script type="text/javascript">
            var canvas = document.getElementById("canvas");
            var context = canvas.getContext('2d');
            var c1 = 1
            var c2 = 1
            var c3 = 1
            var c4 = 1
            var c5 = 1
            var c6 = 1
            var c7 = 1
            var c8 = 1
            var c9 = 1

            var cup1 = 2
            var cup2 = 2
            var cup3 = 2
            var cup4 = 2
            var cup5 = 2
            var cup6 = 2
            var cup7 = 2
            var cup8 = 2
            var cup9 = 2
            //Line horizontale et verticale
            context.beginPath();
            context.moveTo(40,145);
            context.lineTo(360,145);
            context.lineWidth = 5
            context.lineCap = 'round';
            context.stroke();


            context.beginPath();
            context.moveTo(40,260);
            context.lineTo(360,260);
            context.lineCap = 'round';
            context.stroke();


            context.beginPath();
            context.moveTo(260,40);
            context.lineTo(260,360);
            context.lineCap = 'round';
            context.stroke();


            context.beginPath();
            context.moveTo(140,40);
            context.lineTo(140,360);
            context.lineCap = 'round';
            context.stroke();

            context.font = "italic bold 30pt Calibri"
            context.fillText("1", 75, 325);
            context.fillText("2", 190, 325);
            context.fillText("3", 305, 325);
            context.fillText("4", 75, 215);
            context.fillText("5", 190, 215);
            context.fillText("6", 305, 215);
            context.fillText("7", 75, 105);
            context.fillText("8", 190, 105);
            context.fillText("9", 305, 105);

            function Restart(){
                document.location.reload(true);
            }

            document.onkeydown = Nombre;
            Nombreup1 = 49; Nombreup2 = 50; Nombreup3 = 51;
            Nombreup4   = 52; Nombreup5 = 53; Nombreup6 = 54;
            Nombreup7   = 55; Nombreup8 = 56; Nombreup9 = 57;
            Nombre7 = 103; Nombre8 = 104; Nombre9 = 105;
            Nombre4 = 100; Nombre5 = 101; Nombre6 = 102;
            Nombre3 = 99; Nombre2 = 98; Nombre1 = 97;
            function Nombre(e){
                toucheCourante = e.keyCode;

                if (toucheCourante == Nombre7){
                    lettreO7();

                } else if (toucheCourante == Nombre8){
                    lettreO8();

                } else if (toucheCourante == Nombre9){
                    lettreO9();


                } else if (toucheCourante == Nombre6){
                    lettreO6();


                } else if (toucheCourante == Nombre5){
                    lettreO5();


                } else if (toucheCourante == Nombre4){
                    lettreO4();


                } else if (toucheCourante == Nombre3){
                    lettreO3();


                } else if (toucheCourante == Nombre2){
                    lettreO2();


                } else if (toucheCourante == Nombre1){
                    lettreO1();
                }
                /////////////////////////////////////////

                if (toucheCourante == Nombreup7){
                    lettreX7();

                } else if (toucheCourante == Nombreup8){
                    lettreX8();

                } else if (toucheCourante == Nombreup9){
                    lettreX9();

                } else if (toucheCourante == Nombreup6){
                    lettreX6();

                } else if (toucheCourante == Nombreup5){
                    lettreX5();

                } else if (toucheCourante == Nombreup4){
                    lettreX4();

                } else if (toucheCourante == Nombreup3){
                    lettreX3();

                } else if (toucheCourante == Nombreup2){
                    lettreX2();

                } else if (toucheCourante == Nombreup1){
                    lettreX1();
                }
            }


            function lettreO1()
            {
                lettreO = new Image();
                lettreO.src = 'O.jpg';
                lettreO.onload = function(){
                    context.drawImage(lettreO, 40, 265,95,93);
                }
             }

             function lettreX1()
             {
                 lettreX = new Image();
                 lettreX.src = 'X.PNG';
                 lettreX.onload = function(){
                     context.drawImage(lettreX, 40, 265,95,93);
                 }
             }

             function lettreO2()
             {
                 lettreO = new Image();
                 lettreO.src = 'O.jpg';
                 lettreO.onload = function(){
                     context.drawImage(lettreO, 145, 265,110,93);
                 }
             }

             function lettreX2()
             {
                 lettreX = new Image();
                 lettreX.src = 'X.PNG';
                 lettreX.onload = function(){
                     context.drawImage(lettreX, 145, 265,110,93);
                 }
              }

             function lettreO3()
             {
                 lettreO = new Image();
                 lettreO.src = 'O.jpg';
                 lettreO.onload = function(){
                    context.drawImage(lettreO, 265, 265,95,93);
                 }
             }

             function lettreX3()
             {
                 lettreX = new Image();
                 lettreX.src = 'X.PNG';
                 lettreX.onload = function(){
                     context.drawImage(lettreX, 265, 265,95,93);
                 }
             }

            function lettreO4()
            {
                 lettreO = new Image();
                 lettreO.src = 'O.jpg';
                 lettreO.onload = function(){
                     context.drawImage(lettreO, 40,149,95,107);

                 }
             }

            function lettreX4()
            {
                lettreX = new Image();
                lettreX.src = 'X.PNG';
                lettreX.onload = function(){
                   context.drawImage(lettreX, 40,149,95,107);

                }
            }

            function lettreO5()
            {
                lettreO = new Image();
                lettreO.src = 'O.jpg';
                lettreO.onload = function(){
                    context.drawImage(lettreO, 145,149,110,107);

                }
            }

            function lettreX5()
            {
               lettreX = new Image();
               lettreX.src = 'X.PNG';
               lettreX.onload = function(){
                   context.drawImage(lettreX, 145,149,110,107);

               }
            }

            function lettreO6()
            {
                lettreO = new Image();
                lettreO.src = 'O.jpg';
                lettreO.onload = function(){
                    context.drawImage(lettreO, 265,149,95,107);
                }
            }

           function lettreX6()
           {
               lettreX = new Image();
               lettreX.src = 'X.PNG';
               lettreX.onload = function(){
                   context.drawImage(lettreX, 265,149,95,107);

               }
           }

           function lettreO7()
           {
               lettreO = new Image();
               lettreO.src = 'O.jpg';
               lettreO.onload = function(){
                   context.drawImage(lettreO, 40,40,95,101);
               }
            }

            function lettreX7()
            {
                lettreX = new Image();
                lettreX.src = 'X.PNG';
                lettreX.onload = function(){
                    context.drawImage(lettreX, 40,40,95,101);

                }
            }

            function lettreO8()
            {
                lettreO = new Image();
                lettreO.src = 'O.jpg';
                lettreO.onload = function(){
                 context.drawImage(lettreO, 145,40,110,101);

               }
            }
            function lettreX8()
            {
                lettreX = new Image();
                lettreX.src = 'X.PNG';
                lettreX.onload = function(){
                    context.drawImage(lettreX, 145,40,110,101);

                }
            }
            function lettreO9()
            {
                lettreO = new Image();
                lettreO.src = 'O.jpg';
                lettreO.onload = function(){
                    context.drawImage(lettreO, 265,40,95,101);
                }
            }

            function lettreX9()
            {
                lettreX = new Image();
                lettreX.src = 'X.PNG';
                lettreX.onload = function(){
                    context.drawImage(lettreX, 265,40,95,101);
                }
            }
        </script>
    </body>
</html>

标签: javascriptif-statementcanvas

解决方案


我们在聊天中进行了交谈,但由于我不知道我们何时会同时在 SO 上,所以我发布了一个解决方案。如果你愿意,我仍然可以一步一步地帮助你。

首先,我清理并简化了您的代码的某些部分以避免大量工作:

  1. 我将所有用于绘制网格的代码放在一个drawGrid(context)函数中:

从:

// Line horizontale et verticale 

至:

context.fillText("9", 305, 105);
  1. 然后,我重写了function Nombre(e) {...}函数。

我使用了键盘映射:

    var KEYBOARD = {
        NUMBER_UP_1: 49,
        ...
        NUMBER_UP_9: 57,
        NUMBER_1: 97,
        ...
        NUMBER_9: 105,
    };

我重命名了 function function onKeyDown(e) {...},因为Nombre(e)它不是很明确并且可能与Number(n)function 混淆。

我从 keyCode 中推断出这封信。这是一个Xif the keyCodeis in [49, ..., 57],或者一个Oif the keyCodeis in [97, ..., 105]

然后,计算keyCode - {firstKeyCodeForCurrentLetter} - 1会为您提供按下的键上的数字。例如,如果您按50,您有:50 - 49 + 1 = 2,并且根据键盘映射,50与键UP_2相关联。

然后,每当按下数字键(0 除外)时,我都会检查是否有玩家在这里玩过。我创建了一个letterAt(memoryContext, position)函数,如果玩家已经在该位置上场,则返回 true,否则返回 false。如果玩家没有,那么我使用在memorizeMove(memoryContext, letter, position)中绘制的a 保存移动,然后通过在其上绘制 an或 a来memoryCanvas更新主画布。XO

最后,我确定是否有一个获胜者,该winOrLoss(memoryContext)函数返回一个字母:'O'或,如果还没有获胜者,则返回'X'一个空字符串。''

我没有处理平局,也没有处理每个玩家必须等待轮到他玩的事实。所以一个玩家可以连续玩两次。但这是你可以解决的问题。也没有任何适当的游戏结束:如果玩家获胜,则会发出警报,仅此而已,之后游戏仍然可以继续。

但是restart()工作:我在这个函数中初始化了我们需要的一切,所以每次调用它时,它都会清除画布并初始化变量。

我还重写了lettreX1()lettreO3()函数,因为:无需每次绘制时都加载相同的图像。加载一次并根据需要多次使用。然后,您只需将x,y位置分配给一个函数即可在您想要的位置绘制图像,将您的 18 个函数减少到只有一个。

  1. 为了保存游戏的状态,您不想使用变量(例如数组或矩阵来知道已经玩过哪些动作),因此我们同意使用辅助画布。此画布大小为 3x3。每次玩家玩,如果允许移动,那么我们在这个画布上绘制一个像素,这表明该位置不再是空的。一个球员一个颜色。我使用以下memorizeMove(memoryContext, letter, position)功能做到了这一点:
function memorizeMove(memoryContext, letter, position) {
    memoryContext.fillStyle = letter === `O` ? 'red' : 'blue';
    var coords = getCoordinatesFromPosition(position);
    memoryContext.fillRect(coords.x, coords.y, 1, 1);
}

它根据玩家的字母设置颜色(O -> red, X -> blue),从网格中的位置获取x,y坐标,然后在这个位置绘制一个像素,也就是一个1x1的矩形用设定的颜色。

  1. 为了检查是否允许移动,我使用了letterAt(memoryContext, position)将像素颜色(红色、蓝色或空白)转换为字母或空字符串的函数。我本可以只返回 true 或 false,但我需要winOrLoss(memoryContext)函数中的字母,并且我认为稍后知道哪个玩家在这里玩过(如果有的话)也可能很有用。
function letterAt(memoryContext, position) {
    var color = getPixelAt(memoryContext, position);

  return color === 'red' 
    ? 'O'
    : color === 'blue'
        ? 'X'
      : '';
}

它使用 a返回指定 的第二个画布getPixelAt(memoryContext, position)上的像素颜色,如一起看到的。它将 转换为坐标,然后获取 处的像素,获取其RGBA颜色并返回其颜色。memoryContextpositionpositionx,yx,y

function getPixelAt(memoryContext, position) {
  var coords = getCoordinatesFromPosition(position);
  var pixel = memoryContext.getImageData(coords.x, coords.y, 1, 1);
  var data = pixel.data;
  var red = data[0];
  var blue = data[2];
  var color = '';
  if (red === 255) {
    color = 'red';
  } else if (blue === 255) {
    color = 'blue';
  }
  return color;
}
  1. 我写getCoordinatesFromPosition(position)函数的时候有点懒……事实上,你应该使用%/的组合,但是由于你的网格是倒置的(左上角是 7,而不是 1),我认为它可能比预期的要复杂,所以我做了一些非常简单的东西,只使用 ifs。
function getCoordinatesFromPosition(position) {
    var x = [1, 4, 7].includes(position) 
        ? 0
        : [2, 5, 8].includes(position) 
            ? 1
            : 2;
    var y = position < 4 
        ? 2
        : position < 7
            ? 1
            : 0;
    return { x: x, y: y };
}
  1. 最后,对于winOrLoss(memoryContext)函数,我使用函数读取画布letterAt(memoryContext, i)并将它们存储在数组中。然后我比较了彼此之间的字母,水平垂直对角线,寻找 3 个相同的字母。true如果条件满足则返回,false否则返回。
function winOrLoss(memoryContext) {
    var letters = [];
    for (var i = 1; i <= 9; i++) {
        letters.push(letterAt(memoryContext, i));
  }

  if (letters[0] === letters[1] && letters[1] === letters[2] && letters[0] !== ''
        || letters[3] === letters[4] && letters[4] === letters[5] && letters[3] !== ''
        || letters[6] === letters[7] && letters[7] === letters[8] && letters[6] !== ''
        || letters[0] === letters[3] && letters[3] === letters[6] && letters[0] !== ''
        || letters[1] === letters[4] && letters[4] === letters[7] && letters[1] !== ''
        || letters[2] === letters[5] && letters[4] === letters[8] && letters[2] !== ''
        || letters[0] === letters[4] && letters[4] === letters[8] && letters[0] !== ''
        || letters[2] === letters[4] && letters[4] === letters[7] && letters[2] !== ''
      ) {
    return letters[0];
  }
}

像往常一样,这是小提琴:https ://jsfiddle.net/nmerinian/2h87Ltr9/75/


推荐阅读