Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 计算机算法_Javascript_Algorithm_Math - Fatal编程技术网

Javascript 计算机算法

Javascript 计算机算法,javascript,algorithm,math,Javascript,Algorithm,Math,我一直在做一个简单的井字游戏,结果碰到了一堵砖墙 虽然游戏的大部分功能都已经到位,但我缺乏适当放置计算机磁贴所需的关键算法 我需要一种算法,该算法可以搜索一个3x3网格的磁贴,并搜索计算机磁贴在网格中的最佳位置 对于我如何设计这个算法的任何指导或见解,我都将不胜感激 不完全Tic-Tac-Toe算法: function placeComputerTile(el){ if(computerTurn === true && userTurn === false){ var

我一直在做一个简单的井字游戏,结果碰到了一堵砖墙

虽然游戏的大部分功能都已经到位,但我缺乏适当放置计算机磁贴所需的关键算法

我需要一种算法,该算法可以搜索一个3x3网格的磁贴,并搜索计算机磁贴在网格中的最佳位置

对于我如何设计这个算法的任何指导或见解,我都将不胜感激

不完全Tic-Tac-Toe算法:

function placeComputerTile(el){
  if(computerTurn === true && userTurn === false){
    var tileIsEmpty = true;
    // If the selected tile has at least one child,
    // do not allow placement of another tile.
    if (el.firstChild) {
        tileIsEmpty = false;
      }
    if(tileIsEmpty === true){
      cloneComputerIcon();
    }
    el.appendChild(newComputerIcon);
    addClass(el, "x");
    newComputerIcon.style.display = null;
  }
}
完整Javascript:

var gameIcons    = document.getElementsByClassName('gameIcon');
var turnDisplays = document.getElementsByClassName('turnDisplay');

for (var i = 0; i < gameIcons.length; i++) {
  gameIcons[i].style.display = 'none';
}

for (var i = 0; i < turnDisplays.length; i++) {
  turnDisplays[i].style.display = 'none';
}

var userTurn     = true;
var computerTurn = false;
var currentTurn  = 1;
var maxTurn      = 10;

var userTurnDisplay     = document.getElementById("userTurnDisplay");
var computerTurnDisplay = document.getElementById("computerTurnDisplay");

function evaluateTurn(){
  currentTurn += 1;
  for(var i = 0; i < maxTurn; i++) {
    if(currentTurn % 2 === 0){
      userTurn     = true;
      computerTurn = false;
    }else if(currentTurn % 2 !== 0){
      userTurn     = false;
      computerTurn = true;
    }
  }
  if(currentTurn === maxTurn){
    alert("Draw!");
    userTurnDisplay.style.display = "none";
    computerTurnDisplay.style.display = "none";
  }
  //Change display depending on players turn.
  if(userTurn === true && currentTurn !== maxTurn) {
    computerTurnDisplay.style.display = null;
    userTurnDisplay.style.display = "none";
  }else if(computerTurn === true && currentTurn !== maxTurn){
    userTurnDisplay.style.display = null;
    computerTurnDisplay.style.display = "none";
  }
}

var cloneUserIcon = function(){
  var userIcon = document.getElementById("userIcon");
  newUserIcon = userIcon.cloneNode(true);
}

var cloneComputerIcon = function(){
  var computerIcon = document.getElementById("computerIcon");
  newComputerIcon = computerIcon.cloneNode(true);
}

function addClass(el, className) {
  if (el.classList)
    el.classList.add(className)
  else if (!hasClass(el, className)) el.className += " " + className
}

function placeUserTile(el){
  if(userTurn === true && computerTurn === false){
    var tileIsEmpty  = true;
    // If the selected tile has at least one child,
    // do not allow placement of another tile.
    if (el.firstChild) {
      tileIsEmpty = false;
    }
    if(tileIsEmpty === true){
      cloneUserIcon();
    }
    el.appendChild(newUserIcon);
    addClass(el, "o");
    newUserIcon.style.display = null;
  }
}

///////////////////////////////////////////////////////////////////////////////
//                        computer move logic                                //
//                                                                           //

function placeComputerTile(el){
  if(computerTurn === true && userTurn === false){
    var tileIsEmpty = true;
    // If the selected tile has at least one child,
    // do not allow placement of another tile.
    if (el.firstChild) {
        tileIsEmpty = false;
      }
    if(tileIsEmpty === true){
      cloneComputerIcon();
    }
    el.appendChild(newComputerIcon);
    addClass(el, "x");
    newComputerIcon.style.display = null;
  }
}

//                                                                           //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

// Search an array of tiles.
function hasTile(tilesArray){

   var allHaveChild = tilesArray.length > 0;
   for(var i = 0; i < tilesArray.length; i++){
     if(!tilesArray[i].firstChild){
       allHaveChild = false;
     }
   }
   if(allHaveChild)
    return true;
   else
    return false;
}

function hasClass(element, className) {
  return element.className && new RegExp("(^|\\s)" + className + "(\\s|$)").test(element.className);
}

// Row 1 Tiles
const R1C1             = document.getElementById('r1c1');
const R1C2             = document.getElementById('r1c2');
const R1C3             = document.getElementById('r1c3');
//
// // Row 2 Tiles
const R2C1             = document.getElementById('r2c1');
const R2C2             = document.getElementById('r2c2');
const R2C3             = document.getElementById('r2c3');
//
// // Row 3 Tiles
const R3C1             = document.getElementById('r3c1');
const R3C2             = document.getElementById('r3c2');
const R3C3             = document.getElementById('r3c3');

//Set of all row tiles
var rowOneTiles        = [R1C1,R1C2,R1C3];
var rowTwoTiles        = [R2C1,R2C2,R2C3];
var rowThreeTiles      = [R3C1,R3C2,R3C3];

// Set of all column tiles
var columnOneTiles     = [R1C1,R2C1,R3C1];
var columnTwoTiles     = [R1C2,R2C2,R3C2];
var columnThreeTiles   = [R1C3,R2C3,R3C3];

//Set of left-diagonal & right-diagonal tiles
var leftDiagonalTiles  = [R1C1,R2C2,R3C3];
var rightDiagonalTiles = [R1C3,R2C2,R3C1];

function checkRow1(){
  // If the entire row is filled:
  if(hasTile(rowOneTiles)){
    var el_1 = rowOneTiles[0];
    var el_2 = rowOneTiles[1];
    var el_3 = rowOneTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkRow2(){
  // If the entire row is filled:
  if(hasTile(rowTwoTiles)){
    var el_1 = rowTwoTiles[0];
    var el_2 = rowTwoTiles[1];
    var el_3 = rowTwoTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkRow3(){
  // If the entire row is filled:
  if(hasTile(rowThreeTiles)){
    var el_1 = rowThreeTiles[0];
    var el_2 = rowThreeTiles[1];
    var el_3 = rowThreeTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkColumn1(){
  // If the entire row is filled:
  if(hasTile(columnOneTiles)){
    var el_1 = columnOneTiles[0];
    var el_2 = columnOneTiles[1];
    var el_3 = columnOneTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkColumn2(){
  // If the entire row is filled:
  if(hasTile(columnTwoTiles)){
    var el_1 = columnTwoTiles[0];
    var el_2 = columnTwoTiles[1];
    var el_3 = columnTwoTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkColumn3(){
  // If the entire row is filled:
  if(hasTile(columnThreeTiles)){
    var el_1 = columnThreeTiles[0];
    var el_2 = columnThreeTiles[1];
    var el_3 = columnThreeTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkLeftDiagonal(){
  // If the entire row is filled:
  if(hasTile(leftDiagonalTiles)){
    var el_1 = leftDiagonalTiles[0];
    var el_2 = leftDiagonalTiles[1];
    var el_3 = leftDiagonalTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkRightDiagonal(){
  // If the entire row is filled:
  if(hasTile(rightDiagonalTiles)){
    var el_1 = rightDiagonalTiles[0];
    var el_2 = rightDiagonalTiles[1];
    var el_3 = rightDiagonalTiles[2];
    if(hasClass(el_1,"x") && hasClass(el_2,"x") && hasClass(el_3,"x")){
      alert("Sorry, you've lost.");
    }else if(hasClass(el_1,"o") && hasClass(el_2,"o") && hasClass(el_3,"o")){
      alert("Congratulations, you've won!");
    }
  }
}

function checkForWin(){
  checkRow1();
  checkRow2();
  checkRow3();
  checkColumn1();
  checkColumn2();
  checkColumn3();
  checkLeftDiagonal();
  checkRightDiagonal();
}

function main(el){
  evaluateTurn();
  if(userTurn === true){
    placeUserTile(el);
  }
  if(computerTurn === true){
    placeComputerTile(el);
  }
  checkForWin();
}
请查看此链接:

想一想你是如何用一系列if-then语句玩tic-tac-toe的: “如果我先去,然后在中间放一个X”。 “如果我的对手一行有两个O(行、列或对角线中O的计数之和=2),则在该行中放置一个X” 等等等等

清楚地说出你在玩游戏时使用的规则。

如果你不想无聊至死,也不想看到实际的代码,请向下滚动到底部

用于此的典型算法是or,alpha-beta是minimax的优化版本(可能对tac-tic-toe有点过分)。这两种方法基本上都是对你可能得到的位置进行深度优先搜索,在那里你在寻找最好的位置。下面是一个过程的基本示例(下面是一个尝试性的解释):

以下是我对minimax的实现:

/**
*初始化MiniMax(0,player1),其中player1是计算机
*@param depth当前深度或度数
*@param player最大值或最小值
*@return int[]{score,bestRow,bestCol}
*/
int[]miniMax(int深度,int播放器){
//用于放置检查器的可能列的列表
列表移动=下一步移动();
int bestRow=-1;
int-bestCol=-1;
int previousPlayer=(player+1)&1;
//如果达到最大深度或节点是终端节点(游戏结束位置)
//即,如果(当前位置有一个3排| | |您达到最大深度| |电路板已满(绘制))
if(isWin(previousPlayer)| |(depth==this.depth)| | moves.isEmpty()){
返回新的int[]{eval(),bestRow,bestCol};
}
//最佳现值
INTV;
//如果它的最大值(计算机)
如果(玩家==0){
//假设最坏情况下,最大值为-无穷大,
//如果出现更好的值,则用它替换v
v=-inf;
//对于每个可用的移动
对于(int[]move:moves){//move={row,column}
makeMove(move[0],move[1],0);
int分数=极大极小值(深度+1,1)[0];
撤消移动(移动[0],移动[1],0);
//如果得分更好,则更新v
如果(分数>v){
v=分数;
bestRow=移动[0];
bestCol=move[1];
}
}
返回新的int[]{v,bestRow,bestCol};
}
//如果它的最小回合(对手)
否则{
//假设最坏情况下,最小值为无穷大,
//如果出现更好的值,则用它替换v
v=inf;
//对于每个可用的移动
对于(int[]move:moves){//move={row,column}
makeMove(移动[0],移动[1],1);//移动
int分数=极大极小值(深度+1,0)[0];
撤消移动(移动[0],移动[1],1);//撤消移动
//如果得分更好,则更新v
如果(v>分数){
v=分数;
bestRow=移动[0];
bestCol=move[1];
}
}
返回新的int[]{v,bestRow,bestCol};
}
}
对于2名玩家,您为每个玩家分配一个骰子:

1. maximizing player (the computer) 
2. minimizing player (the computer's opponent) 
最大化玩家
获取可用的可能移动的
最大
,类似地
最小化玩家
获取可用的可能移动的
最小

为了阐明此操作,给定您正在查看的位置(或您可能的一次移动导致的位置),您可以通过一些评估函数或参数为其赋值。例如,如果我在玩
X
,并且有以下位置:

=======
|O|X| |
=======
| |X|O|
=======
| |X| |
=======
给出的值应为
(或一些大数字),因为我已经赢了。但如果我有这个职位:

=======
|O| | |
=======
|O|X| |
=======
|X| |X|
=======
value (position){
    if position has a 3 in row return infinity 
    result = 0
    add 1 to result for each 2 in row with an empty space in between
    return result
}
虽然
X
尚未获胜(船上第三排),但
X
肯定会获胜。但是,如果我们想给董事会的当前状态赋值,假设正值表示该位置对
X
有利,我们会将其设为正值。为了满足这一点,您可以,例如,假设行中没有3个,计算所有打开的2个行,并将其作为位置值返回:

=======
|O| | |
=======
|O|X| |
=======
|X| |X|
=======
value (position){
    if position has a 3 in row return infinity 
    result = 0
    add 1 to result for each 2 in row with an empty space in between
    return result
}
因此,对于上面的示例,您将给它一个值
2
(底部水平加上向上向右的对角线)。还有其他更有效的方法来执行评估功能,但上述方法已足够。你也可以
返回infinity
,如果你赢了,但是你的搜索深度可能很大,这不是tic-tac-toe的问题

下面是一个java类,如果您想尝试,它的底部有main方法(和示例):

import java.util.*;
公共f级{
int inf=100000000;//无穷大
智力深度;
字符计算机='O';
字符对手='X';
/*
[0]=计算机
[1] =对手
计算机和对手的移动以二进制数字存储
其中1表示有一个棋盘格,0表示一个棋盘格
空位
=======
|O | O ||
=======
||X||
=======
||X||
=======
上述董事会的代表如下:
计算机=110000000(计算机为“O”)
对手=000010010(对手为“X”)
*/
int[]游戏板={0B10001000000,0b000000000};
//计算i中的位数
整数计数(整数i){
int n=0;
而(i!=0){
i=i&(i-1);
n++;
}
返回n;
value (position){
    if position has a 3 in row return infinity 
    result = 0
    add 1 to result for each 2 in row with an empty space in between
    return result
}
initial board:
=======
|O| | |
=======
| |O| |
=======
| | | |
=======

board after computer move:
=======
|O| | |
=======
| |O| |
=======
| | |O|
=======