Question

Use WebGL to write a program that plays tic-tac-toe. The program should begin by drawing the...

Use WebGL to write a program that plays tic-tac-toe. The program should begin by drawing the game board (two vertical lines and two horizontal lines). When a player left-clicks on an open space, the program should draw an “X” in that square. When a player right-clicks on an open space, the program should draw an “O” in that square. The Xs must be different colors from the Os. Both of those colors must be different from the lines making the game board. In addition, each line or circle must have a width greater than one pixel.


Your program must not use any WebGL primitives other than points. You must write and use your own method that draws a circle given a center point and a radius. You must also write and use your own method that draws a line given two endpoints. The circles should be drawn using the Midpoint Circle algorithm. The lines should be drawn using Bresenham’s Line algorithm.

0 0
Add a comment Improve this question Transcribed image text
Answer #1

Main HTML code for tic-tac-toe:

<html>

  <head>

    <script id="vBoardShader" type="x-shader/x-vertex">

      attribute vec4   aValues;

      varying vec2 vTextureCoord;

      uniform vec2 uTextureCoord[16];

      void main() {

        int textureIndex = int(aValues.w);

        vTextureCoord = uTextureCoord[textureIndex];

        gl_Position = vec4(aValues.x, aValues.y, aValues.z, 1.);

      }

    </script>

    <script id="fBoardShader" type="x-shader/x-fragment">

      precision mediump float;

      varying vec2 vTextureCoord;

      uniform sampler2D uTexture;

      void main() {

           gl_FragColor = texture2D(uTexture, vTextureCoord);

           //gl_FragColor = vec4(1., 0., 0., 1.);

      }

    </script>

    <link type="text/css" rel="stylesheet" href="resources/ticTacToe.css">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>

  </head>

  <body>

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

    <div id="controls" class="control-panel">

        <h1>Tic Tac Toe</h1>

        <label>Choose a Setting:</label>

        <form id="gameType">

            <input id="PvP" type="radio" name="gameType" value="PvP"><label for="PvP">Player vs Player</label><br>

            <input id="PvE" type="radio" name="gameType" value="PvE"><label for="PvE">Player vs Computer</label><br>

            <input id="EvE" type="radio" name="gameType" value="EvE"><label for="EvE">Computer vs Computer</label><br>

        </form>

        <button id="start">Start</button>

        <button id="reset">Reset</button>

    </div>

    <script type="text/javascript">

    "use strict";

    /* CONSTANTS */

    // Web GL Only

    var kTEXTURE_O     = 0;

    var kTEXTURE_X     = 4;

    var kTEXTURE_WHITE = 8;

    var kTEXTURE_BLACK = 12;



    // Constants for the Game

    var kPOSITION_Y_TOP = 8;

    var kPOSITION_Y_MID = 4;

    var kPOSITION_Y_BOT = 0;

    var kPOSITION_X_LEFT  = 16;

    var kPOSITION_X_MID   = 28;

    var kPOSITION_X_RIGHT = 40;

    var kPOISTION_INVALID = -999;

    var kSYMBOL_X = 36;

    var kSYMBOL_O = 0;



    var glContext, glCanvas, glProgram, glVertexBuffer, glIndexArray,

        glIndexBuffer, glTexture, glValueArrLocation;

    var bTextureReady = false;

    var glGameVertexCoords = [];

    var glTextureCoords = [];

    /* Dynamically generates the cross-stitch grid for the game */

    function generateGrid() {

        var height = 1;

        var width = .4;

        var z = 0;

        var texture = kTEXTURE_BLACK;

        for (var i = 0; i < 16; i++) {

            height *= -1;

            if (i % 2 === 0) {

                if (i != 0) {

                    if (Math.abs(width) === .4)

                        width = .3;

                    else

                        width = .4;

                }

            }

            if (width > 0 && (i < 4 || (i >= 8 && i < 12))) {

                width *= -1;

            }

            if (i >= 8) {

                glGameVertexCoords.push(width);

                glGameVertexCoords.push(height);

            } else {

                glGameVertexCoords.push(height);

                glGameVertexCoords.push(width);

            }

            glGameVertexCoords.push(0);

            glGameVertexCoords.push(texture + (i % 4));

        }

    }

    /* Dynamically generates the panels for X and O */

    function generatePanels(texture) {

        var size = .6;

        var baseXOffset = 0;

        var baseYOffset = 0;

        var xOffset = 0;

        var yOffset = 0;

        for (var i = 0; i < 36; i++) {

            if (i % 4 === 0 && i != 0) {

                baseYOffset += .7;

            }

            if (i % 12 === 0 && i != 0) {

                baseXOffset += .7;

                baseYOffset = 0;

            }

            yOffset = baseYOffset;

            xOffset = baseXOffset;

            if (i % 4 === 1) {

                yOffset += size;

            }

            if (i % 4 === 2) {

                xOffset += size;

            }

            if (i % 4 === 3) {

                yOffset += size;

                xOffset += size;

            }

            glGameVertexCoords.push((-1 + xOffset).toFixed(2));

            glGameVertexCoords.push((-1 + yOffset).toFixed(2));

            glGameVertexCoords.push(0);

            glGameVertexCoords.push(texture + (i % 4));

        }

    }

    glTextureCoords = [

            // O

            0.00, 0.25,

            0.00, 0.00,

            0.25, 0.25,

            0.25, 0.00,

            // X

            0.25, 0.25,

            0.25, 0.00,

            0.50, 0.25,

            0.50, 0.00,

            // White

            0.50, 0.25,

            0.50, 0.00,

            0.75, 0.25,

            0.75, 0.00,

            // Black

            0.75, 0.25,

            0.75, 0.00,

            1.00, 0.25,

            1.00, 0.00

    ];

    /* Initalize the webgl program by compiling the shaders */

    function initWebGL() {

        glCanvas = document.getElementById("canvas");

        // Get WebGl context

        glContext = canvas.getContext("webgl");

        if (!glContext) {

            alert("Your browser does not support WebGl");

        }

        //Init Vertex Shader

        var vSrc = document.getElementById("vBoardShader").text;

        var vShader = glContext.createShader(glContext.VERTEX_SHADER);

        glContext.shaderSource(vShader, vSrc);

        glContext.compileShader(vShader);

        //Init Fragment Shader

        var fSrc = document.getElementById("fBoardShader").text;

        var fShader = glContext.createShader(glContext.FRAGMENT_SHADER);

        glContext.shaderSource(fShader, fSrc);

        glContext.compileShader(fShader);

        // link shaders to create our program

        glProgram = glContext.createProgram();

        glContext.attachShader(glProgram, vShader);

        glContext.attachShader(glProgram, fShader);

        glContext.linkProgram(glProgram);

        glContext.useProgram(glProgram);

    }

    /* The texture needs to be loaded into the WebGL layer AFTER the image is

     * "loaded" from the "server" */

    function initTexture() {

        glTexture = glContext.createTexture();

        glTexture.image = new Image();

        glTexture.image.onload = function () {

            glContext.bindTexture(glContext.TEXTURE_2D, glTexture);

            glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA,

                    glContext.RGBA, glContext.UNSIGNED_BYTE,

                    glTexture.image);

            glContext.generateMipmap(glContext.TEXTURE_2D);

            glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, glContext.LINEAR);

            var uniformTextureLocation = glContext.getUniformLocation(glProgram, "uTexture");

            glContext.uniform1i(uniformTextureLocation, 0);

            bTextureReady = true;

        };

        glTexture.image.src = "resources/ticTacToeMap.png";

    }

    /* The first initalization of the arrays used by WebGL. The vertices and

     * texture coordinate are loaded in here as well as the initial index

     * array that draws the gird. */

    function initArrays() {

        generateGrid();

        generatePanels(kTEXTURE_O);

        generatePanels(kTEXTURE_X);

        glIndexArray = [];

        glDrawGrid();

        // Enable the attribute array used to draw vertices

        glValueArrLocation = glContext.getAttribLocation(glProgram, "aValues");

        glContext.enableVertexAttribArray(glValueArrLocation);

        //Vertex Buffer

        glVertexBuffer = glContext.createBuffer();

        glContext.bindBuffer(glContext.ARRAY_BUFFER, glVertexBuffer);

        glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array(glGameVertexCoords), glContext.STATIC_DRAW);

        glIndexBuffer = glContext.createBuffer();

        glContext.bindBuffer(glContext.ELEMENT_ARRAY_BUFFER, glIndexBuffer);

        glContext.bufferData(glContext.ELEMENT_ARRAY_BUFFER, new Uint16Array(glIndexArray), glContext.STATIC_DRAW);

        glContext.vertexAttribPointer(glValueArrLocation, 4, glContext.FLOAT, false, 0, 0);

        var uniformLoc = glContext.getUniformLocation(glProgram, "uTextureCoord");

        // tell webgl how buffer is laid out (pairs of x,y coords)

        glContext.uniform2fv(uniformLoc, new Float32Array(glTextureCoords));

    }


    /* The initalizations functions need to fire in a specific order. The

     * WebGL layer might be delayed by the texture coming from the server. */

    initWebGL();

    initTexture();

    var textureCheck = setTimeout(isTextureReady, 50);

    function isTextureReady() {

        if (bTextureReady) {

            initArrays();

            //Draw Grid

            glUpdate();

            window.clearInterval(textureCheck);

        }

    }

    function glDrawGrid(){

        for (var i = 0; i <= 12; i += 4) {

            // Triangle 1

            glIndexArray.push(i);

            glIndexArray.push(i + 1);

            glIndexArray.push(i + 2);

            // Triangle 2

            glIndexArray.push(i + 1);

            glIndexArray.push(i + 2);

            glIndexArray.push(i + 3);

        }

    }

    // Master update function used to draw elements to the canvas

    function glUpdate() {

        //Clear the canvas

        glContext.clear(glContext.COLOR_BUFFER_BIT);

        //Update Index Buffer

        glContext.bindBuffer(glContext.ELEMENT_ARRAY_BUFFER, glIndexBuffer);

        glContext.bufferData(glContext.ELEMENT_ARRAY_BUFFER, new Uint16Array(glIndexArray), glContext.STATIC_DRAW);

        // Draw

        glContext.drawElements(glContext.TRIANGLES, glIndexArray.length, glContext.UNSIGNED_SHORT, 0);

    }

    // The WebGL function used to add an X or an O to the grid

    function draw(symbol, x, y) {

        var startVertex = x + y + symbol;

        // Triangle 1

        glIndexArray.push(startVertex);

        glIndexArray.push(startVertex + 1);

        glIndexArray.push(startVertex + 2);

        // Triangle 2

        glIndexArray.push(startVertex + 1);

        glIndexArray.push(startVertex + 2);

        glIndexArray.push(startVertex + 3);

        glUpdate();

    }

    function clear(){

        glIndexArray = [];

        glDrawGrid();

        glUpdate();

    }


/*============================================================================*/

    /* UI Management */

    $('#start').click(function (e) {

        if($('input[name="gameType"]:checked').length <= 0) {

            alert("Please select a game type!");

            return;

        }

        //  This logic was based on:

        //  http://jsfiddle.net/codingsolver/MsYqx/

        var gameType = $('input[name="gameType"]:checked', '#gameType').val();

        startGame(gameType);

    });

    //Reset the game on reset click

    $('#reset').click(reset);


//  This logic was based on:

//  http://stackoverflow.com/questions/3234977/using-jquery-how-to-get-click-coordinates-on-the-target-element

    $('#canvas').click(function (e) { //Offset mouse Position

        var posX = e.pageX - $(this).offset().left;

        var posY = e.pageY - $(this).offset().top;

        var x;

        var y;

        if(posY < 116)

            y = kPOSITION_Y_TOP;

        else if(posY > 141 && posY < 257)

            y = kPOSITION_Y_MID;

        else if(posY > 282)

            y = kPOSITION_Y_BOT;

        else

            y = kPOSITION_INVALID;


        if(posX < 116)

            x = kPOSITION_X_LEFT;

        else if(posX > 141 && posX < 257)

            x = kPOSITION_X_MID;

        else if(posX > 282)

            x = kPOSITION_X_RIGHT;

        else

            x = kPOISTION_INVALID;

        if(bUserTurn){

            move(x, y);


        }

    });


/*============================================================================*/

    /* Game Logic */

    /* Constants */

    var kGAME_TYPE_PVP = 0;

    var kGAME_TYPE_PVE = 1;

    var kGAME_TYPE_EVE = 2;

    var gameType;

    var bUserTurn = false;

    var bCompTurn = false;

    var bGameRunning = false;

    var gameMode;

    var turnSymbol;

    var board = [['','',''],

                 ['','',''],

                 ['','','']];

    function startGame(mode) {

        turnSymbol = kSYMBOL_X;

        bGameRunning = true;

        gameMode = mode;

        if (gameMode === 'PvP' || gameMode === 'PvE') {

            bUserTurn = true;

        } else {

            bCompTurn = true;

            computerMove();

        }

    }

    function computerMove() {

        setTimeout(function () {

            var randX = Math.floor(Math.random() * 3);

            var randY = Math.floor(Math.random() * 3);

            while (board[randX][randY] !== '') {

                randX = Math.floor(Math.random() * 3);

                randY = Math.floor(Math.random() * 3);

            }

            var xConsts = [kPOSITION_X_LEFT, kPOSITION_X_MID, kPOSITION_X_RIGHT];

            var yConsts = [kPOSITION_Y_TOP, kPOSITION_Y_MID, kPOSITION_Y_BOT];

            move(xConsts[randX], yConsts[randY]);

        }, 1000);

    }

    function move(x,y) {

        if (bGameRunning) {

            if (x === kPOISTION_INVALID || y === kPOISTION_INVALID) {

                alert("Invalid Selection! Please try again");

                return;

            }

            var boardX;

            switch (x) {

                case kPOSITION_X_LEFT:

                    boardX = 0;

                    break;

                case kPOSITION_X_MID:

                    boardX = 1;

                    break;

                case kPOSITION_X_RIGHT:

                    boardX = 2;

                    break;

            }

            var boardY;

            switch (y) {

                case kPOSITION_Y_TOP:

                    boardY = 0;

                    break;

                case kPOSITION_Y_MID:

                    boardY = 1;

                    break;

                case kPOSITION_Y_BOT:

                    boardY = 2;

                    break;

            }

            if (board[boardX][boardY] === '') {

                board[boardX][boardY] = turnSymbol;

                draw(turnSymbol, x, y);

            } else {

                alert("Selection Already Taken. Please try again.");

                return;

            }

            if (!evaluateGame()) {

                swapSymbol();

                if (gameMode === 'PvE') {

                    bCompTurn = bUserTurn;

                    bUserTurn = !bUserTurn;

                }

                if (bCompTurn) {

                    computerMove();

                }

            }

        }

    }

    function reset() {

        bGameRunning = false;

        board = [['', '', ''],

            ['', '', ''],

            ['', '', '']];

        clear();

    }


    function swapSymbol() {

        if (turnSymbol === kSYMBOL_O) {

            turnSymbol = kSYMBOL_X;

        } else

            turnSymbol = kSYMBOL_O;

    }


    // I'm aware of the nested for loop in this function but this grid is 3x3

    // so I didn't feel the need to optimize. Just like if the grid isn't full

    // enough for a win this check will still occur. TODO:Optimize this check and when it occurs

    function evaluateGame() {

        //Diagonal Check 1

        if (board[0][0] !== '' && board[1][1] !== '' && board[2][2] !== '' &&

                board[0][0] === board[1][1] && board[1][1] === board[2][2]) {

            console.log('Diagonal :' + 0 + '' + 0 + ' Wins!');

            win(board[0][0]);

            return true;

        }

        //Diagonal Check 2

        if (board[0][2] !== '' && board[1][1] !== '' && board[2][0] !== '' &&

                board[0][2] === board[1][1] && board[1][1] === board[2][0]) {

            console.log('Diagonal :' + 0 + '' + 2 + ' Wins!');

            win(board[0][2]);

            return true;

        }

        for (var i = 0; i < board.length; i++) {

            //Column Check

            if (board[i][0] != '' && board[i][0] === board[i][1] &&

                    board[i][1] === board[i][2]) {

                console.log('Column :' + i + ' Wins!');

                win(board[i][0]);

                return true;

            }

            //Row

            if (board[0][i] != '' && board[0][i] === board[1][i] &&

                    board[1][i] === board[2][i]) {

                console.log('Row :' + i + ' Wins!');

                win(board[0][i]);

                return true;

            }

        }

        for (var i = 0; i < board.length; i++) {

            //Check for empty slots

            for (var j = 0; j < board[i].length; j++) {

                if (board[i][j] === '')return false;

            }

        }

        stalemate();

        return true;

    }

    function win(symbol) {

        console.log(symbol);

        if (kSYMBOL_O === symbol) {

            alert('O wins!');

        } else if (kSYMBOL_X === symbol) {

            alert('X wins!');

        } else

            alert('Oops! This shouldn\'t happen! Symbol: ' + symbol);

        bGameRunning = false;

        bUserTurn = false;

    }

    function stalemate() {

        alert('Stalemate!');

    }


    </script>

  </body>

</html>

CSS code:

.canvas{
float: left;
}
.control-panel{
display: inline-block;
height: 100%;
width: 50%;

}

Map file:

Add a comment
Know the answer?
Add Answer to:
Use WebGL to write a program that plays tic-tac-toe. The program should begin by drawing the...
Your Answer:

Post as a guest

Your Name:

What's your source?

Earn Coins

Coins can be redeemed for fabulous gifts.

Not the answer you're looking for? Ask your own homework help question. Our experts will answer your question WITHIN MINUTES for Free.
Similar Homework Help Questions
  • (Tic-Tac-Toe) Create a class Tic-Tac-Toe that will enable you to write a program to play Tic-Tac-Toe....

    (Tic-Tac-Toe) Create a class Tic-Tac-Toe that will enable you to write a program to play Tic-Tac-Toe. The class contains a private 3-by-3 two-dimensional array. Use an enumeration to represent the value in each cell of the array. The enumeration’s constants should be named X, O and EMPTY (for a position that does not contain an X or an O). The constructor should initialize the board elements to EMPTY. Allow two human players. Wherever the first player moves, place an X...

  • 18. Tic-Tac-Toe Game rite a program that allows two players to play a game of tic-tac-toe. Use di...

    18. Tic-Tac-Toe Game rite a program that allows two players to play a game of tic-tac-toe. Use dimensional char array with three rows and three columns as the game board. Each element of the array should be initialized with an asterisk (*). The program should run a loop that does the following: Write . Displays the contents of the board array. . Allows player 1 to select a location on the board for an X. The program should ask the...

  • Write a program to Simulate a game of tic tac toe in c#

    Write a program to Simulate a game of tic tac toe. A game of tic tac toe has two players. A Player class is required to store /represent information about each player. The UML diagram is given below.Player-name: string-symbol :charPlayer (name:string,symbol:char)getName():stringgetSymbol():chargetInfo():string The tic tac toe board will be represented by a two dimensional array of size 3 by 3 characters. At the start of the game each cell is empty (must be set to the underscore character ‘_’). Program flow:1)    ...

  • JAVAFX PROGRAM Write a program that will allow two users to play a game of tic-tac-toe....

    JAVAFX PROGRAM Write a program that will allow two users to play a game of tic-tac-toe. The game area should consist of nine buttons for the play area, a reset button, and a label that will display the current player's turn. When the program starts, the game area buttons should have no values in them (i.e. they should be blank) When player one clicks on a game area button, the button should get the value X. When player two clicks...

  • Tic-Tac-Toe Game Write a program that allows two players to play a game of tic-tac-toe. Use...

    Tic-Tac-Toe Game Write a program that allows two players to play a game of tic-tac-toe. Use a two-dimensional char array with three rows and three columns as the game board. Each element of the array should be initialized with an asterisk (*). The program should run a loop that does the following: Displays the contents of the board array. Allows player 1 to select a location on the board for an X. The program should ask the user to enter...

  • Please make this into one class. JAVA Please: Tic Tac Toe class - Write a fifth...

    Please make this into one class. JAVA Please: Tic Tac Toe class - Write a fifth game program that can play Tic Tac Toe. This game displays the lines of the Tic Tac Toe game and prompts the player to choose a move. The move is recorded on the screen and the computer picks his move from those that are left. The player then picks his next move. The program should allow only legal moves. The program should indicate when...

  • JAVA TIC TAC TOE - please help me correct my code Write a program that will...

    JAVA TIC TAC TOE - please help me correct my code Write a program that will allow two players to play a game of TIC TAC TOE. When the program starts, it will display a tic tac toe board as below |    1       |   2        |   3 |    4       |   5        |   6                 |    7      |   8        |   9 The program will assign X to Player 1, and O to Player    The program will ask Player 1, to...

  • Write a c program that will allow two users to play a tic-tac-toe game. You should...

    Write a c program that will allow two users to play a tic-tac-toe game. You should write the program such that two people can play the game without any special instructions. (assue they know how to play the game). Prompt first player(X) to enter their first move. .Then draw the gameboard showing the move. .Prompt the second player(O) to enter their first move. . Then draw the gameboard showing both moves. And so on...through 9 moves. You will need to:...

  • 1. Use Turtle Graphics to create a tic tac toe game in Python. Write a Python program that allows for one player vs computer to play tic tac toe game, without using turtle.turtle

    1. Use Turtle Graphics to create a tic tac toe game in Python. Write a Python program that allows for one player vs computer to play tic tac toe game, without using turtle.turtle

  • (Tic-Tac-Toe) Create class TicTacToe that will enable you to write a complete app to play the...

    (Tic-Tac-Toe) Create class TicTacToe that will enable you to write a complete app to play the game of Tic-Tac-Toe. The class contains a private 3-by-3 rectangular array of integers. The constructor should initialize the empty board to all 0s. Allow two human players. Wherever the first player moves, place a 1 in the specified square, and place a 2 wherever the second player moves. Each move must be to an empty square. After each move, determine whether the game has...

ADVERTISEMENT
Free Homework Help App
Download From Google Play
Scan Your Homework
to Get Instant Free Answers
Need Online Homework Help?
Ask a Question
Get Answers For Free
Most questions answered within 3 hours.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT