我正在创建一个tic-tac-toe的JavaScript游戏,并尝试使其足够聪明,根据维基百科文章中概述的策略进行明智的移动。 I.E.,如果有一行或一列有两个X或两个Os,则取空点。因此,给定一行或一列键值对,假设值可能是:obj {key1:“X”,key2:“”,key3:“X”,}
我一直在研究这样做的方法,并且好奇是否有办法除了一系列循环之外还有其他方法。我的第一次尝试是尝试按字母顺序对项目进行排序,以便我可以隔离空白值:var =“”,“X”,“X”
在这种情况下,我可以轻松地调用第一个项目并更新它,但我不能将其反转为它是什么,并将其更新到它在对象中的原始位置。但是,我似乎无法弄清楚如何以不会产生大量浪费代码的方式执行此操作。分成多个循环可能会更好吗?一个隔离有一个空白点的行和列(其中有8个)?
我的另一个想法是给网格中的每个值一个值1,然后查看网格,如果一行等于3(创建连接它们并使用.eval()方法的var),那么每个item等于1,因此将空白点更新为1并更新已经为1的其他两个点。
我承认,我试图尽可能具体,但我并不擅长解释这个特殊问题。
这是我制作的JS小提琴:https://jsfiddle.net/1hup5195/
以下是我的一些脚本供参考:
$(document).ready(function(){
var playerTurn = true;
var buttonStatus = "allowclick"; // Change to inactive once game starts
var player = "";
var machine = "";
var test = "";
var emptyObj = {1: "", 2: "", 3: "",
4: "", 5: "", 6: "",
7: "", 8: "", 9: ""};
var gridObj = {1: "", 2: "", 3: "",
4: "", 5: "", 6: "",
7: "", 8: "", 9: ""};
var winningObj = [[1,2,3], [4,5,6], [7,8,9], [1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]];
// Check if player is holding a corner
function machineFunction() {
// Loop through winningObj and check if there are rows/columns with 2/3 taken
// for(i = 0; i < winningObj.length; i++) {
var i = 3;
var alpha = winningObj[i][0];
var bravo = winningObj[i][1];
var charlie = winningObj[i][2];
console.log(alpha);
console.log(bravo);
console.log(charlie);
// After defining alpha/bravo/charlie, fire the fxn
testFxn(alpha, bravo, charlie);
// This is my function to sort the 3 different spots within the grid
function testFxn(a,b,c) {
// Test would be equal to ["", "X", "X"] or something similar
var test = [gridObj[a], gridObj[b], gridObj[c]].sort();
console.log(test);
console.log(gridObj);
// If 2/3 spots taken by either X or O, take this spot
if (test[0] === "" && test[1] === "X" && test[2] === "X") {
console.log("#" + alpha + "")
$('#' + alpha + '').html(machine);
gridObj[alpha] = machine;
console.log(gridObj);
$(this).html(machine); // Sends player over to html
gridObj[this.id] = machine; // Update gridObj object
playerTurn = true;
}
if (test[0] === "" && test[1] === "O" && test[2] === "O") {
// How do I get the ID I need??
$('#' + test[0] + '').html(machine);
playerTurn = true;
}
};
我想评论,但我不能。所以这是我的评论作为回答......
如果您创建每个“字段”的对象,则可以在不同的数组中引用它。因此,您可以执行array.copy,对其进行排序,然后更改对象中的值。
这也将设置包含相同对象的其他数组中的值。
祝好运!
你可以这样做(用一些来迭代...):
var rows = [[1,2,3], [4,5,6], [7,8,9], [1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]];
var gridObj = {1: "", 2: "", 3: "",
4: "", 5: "", 6: "",
7: "", 8: "", 9: ""};
rows.some(function(row){//iterate over all rows
var values=row.map(key=>gridObj[key]);//get the rows values
if(values.filter(el=>el==="X").length===2){//check if there are two Xses
gridObj[rows[values.indexOf("")]]="O";//get the field id and add O to the blank field
return true;//stop iterating the rows
}
});
Javascript有一个很棒的函数叫做map
,可以用在数组上。 Here is documentation。
映射的作用是提供一个回调函数,它将对数组中的每个元素执行一些已定义的函数(可能根据当前状态检查获胜状态),并返回一个包含已更改或未更改值的新数组。例如,您可以像现在一样拥有一系列获胜状态,并且可以
var winner = winningObj.map((item) => { // ()=>{} is ES6 syntax. Same as function(){}
var token = {}
if currentState[item[0]] != empty
token.1st = X
if currentState[item[1]] != empty
token.2nd = X
if currentState[item[2]] != empty
token.3rd = X
if all tokens are X
return X // winner!
else if all tokens are O
return O // check the other winning conditions, or keep playing
else
return false
);
if winner.containsValue(X)
X wins
else if winner.containsValue(O)
O wins
else
keep playing
我知道这并没有真正回答你提出更高效率的问题,但这样你就可以避免写出任何循环,让map()
为你做所有工作。