From 4b301332f9d089ef7f6541356bf0bc2488486466 Mon Sep 17 00:00:00 2001 From: unknown <{sanathan6522@gmail.com}> Date: Tue, 17 Oct 2023 13:11:09 +0530 Subject: [PATCH] tictactoe using js --- TicTacToeGame/sanathan-git/README.md | 10 + TicTacToeGame/sanathan-git/index.html | 66 +++ TicTacToeGame/sanathan-git/main.js | 617 ++++++++++++++++++++++++++ TicTacToeGame/sanathan-git/style.css | 155 +++++++ 4 files changed, 848 insertions(+) create mode 100644 TicTacToeGame/sanathan-git/README.md create mode 100644 TicTacToeGame/sanathan-git/index.html create mode 100644 TicTacToeGame/sanathan-git/main.js create mode 100644 TicTacToeGame/sanathan-git/style.css diff --git a/TicTacToeGame/sanathan-git/README.md b/TicTacToeGame/sanathan-git/README.md new file mode 100644 index 000000000..20d709e7c --- /dev/null +++ b/TicTacToeGame/sanathan-git/README.md @@ -0,0 +1,10 @@ +# A website built with HTML,CSS,Javascript + +## How to use +- click on setting icon set the difficulty level +- select one option +- Player which made the straight line first wins. + +## How to start +- open the index.html file in your browser. + diff --git a/TicTacToeGame/sanathan-git/index.html b/TicTacToeGame/sanathan-git/index.html new file mode 100644 index 000000000..7a7481e7c --- /dev/null +++ b/TicTacToeGame/sanathan-git/index.html @@ -0,0 +1,66 @@ + + + + + + + Tic_tac_toe + + + + + + + Tic-tac-toe + + + + +

◥◣ Tic-Tac-Toe ◢◤

+ + + + +
+
⚙️
+ + + +
Robot TieYou
000
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/TicTacToeGame/sanathan-git/main.js b/TicTacToeGame/sanathan-git/main.js new file mode 100644 index 000000000..ace72187d --- /dev/null +++ b/TicTacToeGame/sanathan-git/main.js @@ -0,0 +1,617 @@ +"use strict"; + +// Bind Esc key to closing the modal dialog +document.onkeypress = function (evt) { + evt = evt || window.event; + var modal = document.getElementsByClassName("modal")[0]; + if (evt.keyCode === 27) { + modal.style.display = "none"; + } +}; + +// When the user clicks anywhere outside of the modal dialog, close it +window.onclick = function (evt) { + var modal = document.getElementsByClassName("modal")[0]; + if (evt.target === modal) { + modal.style.display = "none"; + } +}; + +//================================== +// HELPER FUNCTIONS +//================================== +function sumArray(array) { + var sum = 0, + i = 0; + for (i = 0; i < array.length; i++) { + sum += array[i]; + } + return sum; +} + +function isInArray(element, array) { + if (array.indexOf(element) > -1) { + return true; + } + return false; +} + +function shuffleArray(array) { + var counter = array.length, + temp, + index; + while (counter > 0) { + index = Math.floor(Math.random() * counter); + counter--; + temp = array[counter]; + array[counter] = array[index]; + array[index] = temp; + } + return array; +} + +function intRandom(min, max) { + var rand = min + Math.random() * (max + 1 - min); + return Math.floor(rand); +} + +// GLOBAL VARIABLES +var moves = 0, + winner = 0, + x = 1, + o = 3, + player = x, + computer = o, + whoseTurn = x, + gameOver = false, + score = { + ties: 0, + player: 0, + computer: 0 + }, + xText = "×", + oText = "o", + playerText = xText, + computerText = oText, + difficulty = 1, + myGrid = null; + +//================================== +// GRID OBJECT +//================================== + +// Grid constructor +//================= +function Grid() { + this.cells = new Array(9); +} + +// Grid methods +//============= + +// Get free cells in an array. +// Returns an array of indices in the original Grid.cells array, not the values +// of the array elements. +// Their values can be accessed as Grid.cells[index]. +Grid.prototype.getFreeCellIndices = function () { + var i = 0, + resultArray = []; + for (i = 0; i < this.cells.length; i++) { + if (this.cells[i] === 0) { + resultArray.push(i); + } + } + // console.log("resultArray: " + resultArray.toString()); + // debugger; + return resultArray; +}; + +// Get a row (accepts 0, 1, or 2 as argument). +// Returns the values of the elements. +Grid.prototype.getRowValues = function (index) { + if (index !== 0 && index !== 1 && index !== 2) { + console.error("Wrong arg for getRowValues!"); + return undefined; + } + var i = index * 3; + return this.cells.slice(i, i + 3); +}; + +// Get a row (accepts 0, 1, or 2 as argument). +// Returns an array with the indices, not their values. +Grid.prototype.getRowIndices = function (index) { + if (index !== 0 && index !== 1 && index !== 2) { + console.error("Wrong arg for getRowIndices!"); + return undefined; + } + var row = []; + index = index * 3; + row.push(index); + row.push(index + 1); + row.push(index + 2); + return row; +}; + +// get a column (values) +Grid.prototype.getColumnValues = function (index) { + if (index !== 0 && index !== 1 && index !== 2) { + console.error("Wrong arg for getColumnValues!"); + return undefined; + } + var i, column = []; + for (i = index; i < this.cells.length; i += 3) { + column.push(this.cells[i]); + } + return column; +}; + +// get a column (indices) +Grid.prototype.getColumnIndices = function (index) { + if (index !== 0 && index !== 1 && index !== 2) { + console.error("Wrong arg for getColumnIndices!"); + return undefined; + } + var i, column = []; + for (i = index; i < this.cells.length; i += 3) { + column.push(i); + } + return column; +}; + +// get diagonal cells +// arg 0: from top-left +// arg 1: from top-right +Grid.prototype.getDiagValues = function (arg) { + var cells = []; + if (arg !== 1 && arg !== 0) { + console.error("Wrong arg for getDiagValues!"); + return undefined; + } else if (arg === 0) { + cells.push(this.cells[0]); + cells.push(this.cells[4]); + cells.push(this.cells[8]); + } else { + cells.push(this.cells[2]); + cells.push(this.cells[4]); + cells.push(this.cells[6]); + } + return cells; +}; + +// get diagonal cells +// arg 0: from top-left +// arg 1: from top-right +Grid.prototype.getDiagIndices = function (arg) { + if (arg !== 1 && arg !== 0) { + console.error("Wrong arg for getDiagIndices!"); + return undefined; + } else if (arg === 0) { + return [0, 4, 8]; + } else { + return [2, 4, 6]; + } +}; + +// Get first index with two in a row (accepts computer or player as argument) +Grid.prototype.getFirstWithTwoInARow = function (agent) { + if (agent !== computer && agent !== player) { + console.error("Function getFirstWithTwoInARow accepts only player or computer as argument."); + return undefined; + } + var sum = agent * 2, + freeCells = shuffleArray(this.getFreeCellIndices()); + for (var i = 0; i < freeCells.length; i++) { + for (var j = 0; j < 3; j++) { + var rowV = this.getRowValues(j); + var rowI = this.getRowIndices(j); + var colV = this.getColumnValues(j); + var colI = this.getColumnIndices(j); + if (sumArray(rowV) == sum && isInArray(freeCells[i], rowI)) { + return freeCells[i]; + } else if (sumArray(colV) == sum && isInArray(freeCells[i], colI)) { + return freeCells[i]; + } + } + for (j = 0; j < 2; j++) { + var diagV = this.getDiagValues(j); + var diagI = this.getDiagIndices(j); + if (sumArray(diagV) == sum && isInArray(freeCells[i], diagI)) { + return freeCells[i]; + } + } + } + return false; +}; + +Grid.prototype.reset = function () { + for (var i = 0; i < this.cells.length; i++) { + this.cells[i] = 0; + } + return true; +}; + +//================================== +// MAIN FUNCTIONS +//================================== + +// executed when the page loads +function initialize() { + myGrid = new Grid(); + moves = 0; + winner = 0; + gameOver = false; + whoseTurn = player; // default, this may change + for (var i = 0; i <= myGrid.cells.length - 1; i++) { + myGrid.cells[i] = 0; + } + // setTimeout(assignRoles, 500); + setTimeout(showOptions, 500); + // debugger; +} + +// Ask player if they want to play as X or O. X goes first. +function assignRoles() { + askUser("Do you want to go first? "); + document.getElementById("yesBtn").addEventListener("click", makePlayerX); + document.getElementById("noBtn").addEventListener("click", makePlayerO); +} + +function makePlayerX() { + player = x; + computer = o; + whoseTurn = player; + playerText = xText; + computerText = oText; + document.getElementById("userFeedback").style.display = "none"; + document.getElementById("yesBtn").removeEventListener("click", makePlayerX); + document.getElementById("noBtn").removeEventListener("click", makePlayerO); +} + +function makePlayerO() { + player = o; + computer = x; + whoseTurn = computer; + playerText = oText; + computerText = xText; + setTimeout(makeComputerMove, 400); + document.getElementById("userFeedback").style.display = "none"; + document.getElementById("yesBtn").removeEventListener("click", makePlayerX); + document.getElementById("noBtn").removeEventListener("click", makePlayerO); +} + +// executed when player clicks one of the table cells +function cellClicked(id) { + // The last character of the id corresponds to the numeric index in Grid.cells: + var idName = id.toString(); + var cell = parseInt(idName[idName.length - 1]); + if (myGrid.cells[cell] > 0 || whoseTurn !== player || gameOver) { + // cell is already occupied or something else is wrong + return false; + } + moves += 1; + document.getElementById(id).innerHTML = playerText; + // randomize orientation (for looks only) + var rand = Math.random(); + if (rand < 0.3) { + document.getElementById(id).style.transform = "rotate(180deg)"; + } else if (rand > 0.6) { + document.getElementById(id).style.transform = "rotate(90deg)"; + } + document.getElementById(id).style.cursor = "default"; + myGrid.cells[cell] = player; + // Test if we have a winner: + if (moves >= 5) { + winner = checkWin(); + } + if (winner === 0) { + whoseTurn = computer; + makeComputerMove(); + } + return true; +} + +// Executed when player hits restart button. +// ask should be true if we should ask users if they want to play as X or O +function restartGame(ask) { + if (moves > 0) { + var response = confirm("Are you sure you want to start over?"); + if (response === false) { + return; + } + } + gameOver = false; + moves = 0; + winner = 0; + whoseTurn = x; + myGrid.reset(); + for (var i = 0; i <= 8; i++) { + var id = "cell" + i.toString(); + document.getElementById(id).innerHTML = ""; + document.getElementById(id).style.cursor = "pointer"; + document.getElementById(id).classList.remove("win-color"); + } + if (ask === true) { + // setTimeout(assignRoles, 200); + setTimeout(showOptions, 200); + } else if (whoseTurn == computer) { + setTimeout(makeComputerMove, 800); + } +} + +// The core logic of the game AI: +function makeComputerMove() { + // debugger; + if (gameOver) { + return false; + } + var cell = -1, + myArr = [], + corners = [0,2,6,8]; + if (moves >= 3) { + cell = myGrid.getFirstWithTwoInARow(computer); + if (cell === false) { + cell = myGrid.getFirstWithTwoInARow(player); + } + if (cell === false) { + if (myGrid.cells[4] === 0 && difficulty == 1) { + cell = 4; + } else { + myArr = myGrid.getFreeCellIndices(); + cell = myArr[intRandom(0, myArr.length - 1)]; + } + } + // Avoid a catch-22 situation: + if (moves == 3 && myGrid.cells[4] == computer && player == x && difficulty == 1) { + if (myGrid.cells[7] == player && (myGrid.cells[0] == player || myGrid.cells[2] == player)) { + myArr = [6,8]; + cell = myArr[intRandom(0,1)]; + } + else if (myGrid.cells[5] == player && (myGrid.cells[0] == player || myGrid.cells[6] == player)) { + myArr = [2,8]; + cell = myArr[intRandom(0,1)]; + } + else if (myGrid.cells[3] == player && (myGrid.cells[2] == player || myGrid.cells[8] == player)) { + myArr = [0,6]; + cell = myArr[intRandom(0,1)]; + } + else if (myGrid.cells[1] == player && (myGrid.cells[6] == player || myGrid.cells[8] == player)) { + myArr = [0,2]; + cell = myArr[intRandom(0,1)]; + } + } + else if (moves == 3 && myGrid.cells[4] == player && player == x && difficulty == 1) { + if (myGrid.cells[2] == player && myGrid.cells[6] == computer) { + cell = 8; + } + else if (myGrid.cells[0] == player && myGrid.cells[8] == computer) { + cell = 6; + } + else if (myGrid.cells[8] == player && myGrid.cells[0] == computer) { + cell = 2; + } + else if (myGrid.cells[6] == player && myGrid.cells[2] == computer) { + cell = 0; + } + } + } else if (moves === 1 && myGrid.cells[4] == player && difficulty == 1) { + // if player is X and played center, play one of the corners + cell = corners[intRandom(0,3)]; + } else if (moves === 2 && myGrid.cells[4] == player && computer == x && difficulty == 1) { + // if player is O and played center, take two opposite corners + if (myGrid.cells[0] == computer) { + cell = 8; + } + else if (myGrid.cells[2] == computer) { + cell = 6; + } + else if (myGrid.cells[6] == computer) { + cell = 2; + } + else if (myGrid.cells[8] == computer) { + cell = 0; + } + } else if (moves === 0 && intRandom(1,10) < 8) { + // if computer is X, start with one of the corners sometimes + cell = corners[intRandom(0,3)]; + } else { + // choose the center of the board if possible + if (myGrid.cells[4] === 0 && difficulty == 1) { + cell = 4; + } else { + myArr = myGrid.getFreeCellIndices(); + cell = myArr[intRandom(0, myArr.length - 1)]; + } + } + var id = "cell" + cell.toString(); + // console.log("computer chooses " + id); + document.getElementById(id).innerHTML = computerText; + document.getElementById(id).style.cursor = "default"; + // randomize rotation of marks on the board to make them look + // as if they were handwritten + var rand = Math.random(); + if (rand < 0.3) { + document.getElementById(id).style.transform = "rotate(180deg)"; + } else if (rand > 0.6) { + document.getElementById(id).style.transform = "rotate(90deg)"; + } + myGrid.cells[cell] = computer; + moves += 1; + if (moves >= 5) { + winner = checkWin(); + } + if (winner === 0 && !gameOver) { + whoseTurn = player; + } +} + +// Check if the game is over and determine winner +function checkWin() { + winner = 0; + + // rows + for (var i = 0; i <= 2; i++) { + var row = myGrid.getRowValues(i); + if (row[0] > 0 && row[0] == row[1] && row[0] == row[2]) { + if (row[0] == computer) { + score.computer++; + winner = computer; + // console.log("computer wins"); + } else { + score.player++; + winner = player; + // console.log("player wins"); + } + // Give the winning row/column/diagonal a different bg-color + var tmpAr = myGrid.getRowIndices(i); + for (var j = 0; j < tmpAr.length; j++) { + var str = "cell" + tmpAr[j]; + document.getElementById(str).classList.add("win-color"); + } + setTimeout(endGame, 1000, winner); + return winner; + } + } + + // columns + for (i = 0; i <= 2; i++) { + var col = myGrid.getColumnValues(i); + if (col[0] > 0 && col[0] == col[1] && col[0] == col[2]) { + if (col[0] == computer) { + score.computer++; + winner = computer; + // console.log("computer wins"); + } else { + score.player++; + winner = player; + // console.log("player wins"); + } + // Give the winning row/column/diagonal a different bg-color + var tmpAr = myGrid.getColumnIndices(i); + for (var j = 0; j < tmpAr.length; j++) { + var str = "cell" + tmpAr[j]; + document.getElementById(str).classList.add("win-color"); + } + setTimeout(endGame, 1000, winner); + return winner; + } + } + + // diagonals + for (i = 0; i <= 1; i++) { + var diagonal = myGrid.getDiagValues(i); + if (diagonal[0] > 0 && diagonal[0] == diagonal[1] && diagonal[0] == diagonal[2]) { + if (diagonal[0] == computer) { + score.computer++; + winner = computer; + // console.log("computer wins"); + } else { + score.player++; + winner = player; + // console.log("player wins"); + } + // Give the winning row/column/diagonal a different bg-color + var tmpAr = myGrid.getDiagIndices(i); + for (var j = 0; j < tmpAr.length; j++) { + var str = "cell" + tmpAr[j]; + document.getElementById(str).classList.add("win-color"); + } + setTimeout(endGame, 1000, winner); + return winner; + } + } + + // If we haven't returned a winner by now, if the board is full, it's a tie + var myArr = myGrid.getFreeCellIndices(); + if (myArr.length === 0) { + winner = 10; + score.ties++; + endGame(winner); + return winner; + } + + return winner; +} + +function announceWinner(text) { + document.getElementById("winText").innerHTML = text; + document.getElementById("winAnnounce").style.display = "block"; + setTimeout(closeModal, 5000, "winAnnounce"); +} + +function askUser(text) { + document.getElementById("questionText").innerHTML = text; + document.getElementById("userFeedback").style.display = "block"; +} + +function showOptions() { + if (player == o) { + document.getElementById("rx").checked = false; + document.getElementById("ro").checked = true; + } + else if (player == x) { + document.getElementById("rx").checked = true; + document.getElementById("ro").checked = false; + } + if (difficulty === 0) { + document.getElementById("r0").checked = true; + document.getElementById("r1").checked = false; + } + else { + document.getElementById("r0").checked = false; + document.getElementById("r1").checked = true; + } + document.getElementById("optionsDlg").style.display = "block"; +} + +function getOptions() { + var diffs = document.getElementsByName('difficulty'); + for (var i = 0; i < diffs.length; i++) { + if (diffs[i].checked) { + difficulty = parseInt(diffs[i].value); + break; + // debugger; + } + } + if (document.getElementById('rx').checked === true) { + player = x; + computer = o; + whoseTurn = player; + playerText = xText; + computerText = oText; + } + else { + player = o; + computer = x; + whoseTurn = computer; + playerText = oText; + computerText = xText; + setTimeout(makeComputerMove, 400); + } + document.getElementById("optionsDlg").style.display = "none"; +} + +function closeModal(id) { + document.getElementById(id).style.display = "none"; +} + +function endGame(who) { + if (who == player) { + announceWinner("Congratulations🥳, you won!👏"); + } else if (who == computer) { + announceWinner("Oops!😵Robot wins😀!"); + } else { + announceWinner("It's a tie!🤷‍♂️"); + } + gameOver = true; + whoseTurn = 0; + moves = 0; + winner = 0; + document.getElementById("computer_score").innerHTML = score.computer; + document.getElementById("tie_score").innerHTML = score.ties; + document.getElementById("player_score").innerHTML = score.player; + for (var i = 0; i <= 8; i++) { + var id = "cell" + i.toString(); + document.getElementById(id).style.cursor = "default"; + } + setTimeout(restartGame, 800); +} diff --git a/TicTacToeGame/sanathan-git/style.css b/TicTacToeGame/sanathan-git/style.css new file mode 100644 index 000000000..e5c0a3cf7 --- /dev/null +++ b/TicTacToeGame/sanathan-git/style.css @@ -0,0 +1,155 @@ +@import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap'); + +body { + background-color: rgb(32, 32, 32); + background-image: url("https://images.unsplash.com/photo-1614292253351-4deb4913c142?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80"); + background-repeat: no-repeat; + color: rgb(230, 230, 230); + text-align: center; + font-family: 'Varela Round', sans-serif; + font-size: 0.7em; +} +h1 { + line-height: 1em; + margin: 15px; + padding-bottom: 5px; + font-size: 3.5em; + font-weight: 500; + color: whitesmoke; +} +h2 { + font-size: 1.3em; + font-weight: bold; + padding: 0; + margin: 15px; + +} +h3 { + font-size: 1.1em; + text-decoration: underline; + padding: 0; + margin: 15px; +} +table { + margin: 2% auto; + border-collapse: collapse; +} +#table_game { + position: relative; + font-size: 120px; + margin: 1% auto; + border-collapse: collapse; +} +.td_game { + border: 4px solid rgb(230, 230, 230); + bborder-top: none; + width: 90px; + height: 90px; + padding: 0; + vertical-align: middle; + text-align: center; +} +.fixed { + width: 90px; + height: 90px; + line-height: 90px; + display: block; + overflow: hidden; + cursor: pointer; +} +.td_list { + text-align: center; + font-size: 1.3em; + font-weight: bold; +} +.th_list { + font-size: 1.3em; + font-weight: bold; + text-align: center; + text-decoration: underline; +} +#restart { + font-size: 3em; + width: 1em; + height: 0.9em; + cursor: pointer; + margin: 0 auto; + overflow: hidden; +} +.x { + color: darksalmon; + position: relative; + top: -8px; + font-size: 1.2em; + cursor: default; +} +.o { + color: aquamarine; + position: relative; + top: -7px; + font-size: 1em; + cursor: default; +} + +/* modal background */ +.modal { + display: none; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; /* enable scroll if needed */ + background-color: black; /* fallback color */ + background-color: rgba(0, 0, 0, 0.6); +} + +/* modal content */ +.modal-content { + background-color: rgb(240, 240, 240); + color: rgb(32, 32, 32); + font-size: 2em; + font-weight: bold; + /* 16 % from the top and centered */ + margin: 16% auto; + padding: 20px; + border-radius: 10px; + width: 380px; + max-width: 80%; +} +.modal-content p { + margin: 0; + padding: 0; +} + +/* close button for modal dialog */ +.close { + color: rgb(170, 170, 170); + float: right; + position: relative; + top: -25px; + right: -10px; + font-size: 34px; + font-weight: bold; +} +.close:hover, +.close:focus { + color: black; + text-decoration: none; + cursor: pointer; +} + +.win-color { + background-color: rgb(240, 240, 240); +} +#okBtn{ + font-size: 15px; + padding: 5px; + width: 70px; + margin: 15px; + background: none; + border: none; + border-bottom: 2px solid black; + cursor: pointor; +}