Я делаю крестики-нолики 4x4x4 с тремя js, и чтобы проверить условие выигрыша, я создал логический массив. Поскольку блоков 16 * 4 = 64, я создал логический массив размером 64 и по умолчанию установил для него значение false. И затем всякий раз, когда пользователь щелкает один из блоков, он динамически изменяет выбранный объект на true. Чтобы проверить условие выигрыша по горизонтали, я использовал это,
var camera, scene, renderer, mesh, material, controls;
var targetList = [];
var targetListBool = new Array(64).fill(false);
console.info(targetListBool);
// var projector, mouse = { x: 0, y: 0 };
var projecter;
var mouse = new THREE.Vector2(),
INTERSECTED;
init();
animate();
addCubes();
render();
function addCubes() {
var xDistance = 30;
var zDistance = 15;
var geometry = new THREE.BoxBufferGeometry(10, 10, 10);
var material = new THREE.MeshBasicMaterial({
color: 0x6C70A8
});
//initial offset so does not start in middle.
var xOffset = -80;
//1
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
var mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: 0xadc9f4
}));
mesh.position.x = (xDistance * (i)) + xOffset;
mesh.position.z = (zDistance * (j));
scene.add(mesh);
targetList.push(mesh);
}
//2
for (let j = 0; j < 4; j++) {
var mesh2 = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: 0xadc9f4
}));
mesh2.position.x = (xDistance * (i)) + xOffset;
mesh2.position.z = (zDistance * (j));
mesh2.position.y = 15;
scene.add(mesh2);
targetList.push(mesh2);
}
//3
for (let j = 0; j < 4; j++) {
var mesh3 = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: 0xadc9f4
}));
mesh3.position.x = (xDistance * (i)) + xOffset;
mesh3.position.z = (zDistance * (j));
mesh3.position.y = 30;
scene.add(mesh3);
targetList.push(mesh3);
}
//4
for (let j = 0; j < 4; j++) {
var mesh4 = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: 0xadc9f4
}));
mesh4.position.x = (xDistance * (i)) + xOffset;
mesh4.position.z = (zDistance * (j));
mesh4.position.y = 45;
scene.add(mesh4);
targetList.push(mesh4);
}
}
for (var i = 0; i < targetList.length; i++) {
targetList[i].name = i;
}
}
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({
antialias: true
});
// renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 150;
// Add controls
controls = new THREE.TrackballControls(camera);
controls.addEventListener('change', render);
controls.target.set(0, 0, -50);
// Create scene.
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
// Create directional light and add to scene.
var pointLight = new THREE.PointLight(0xFFFFFF, 1, 100000);
pointLight.position.set(1, 1, 1).normalize();
scene.add(pointLight);
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
}
// initialize object to perform world/screen calculations
projector = new THREE.Projector();
// when the mouse moves, call the given function
document.addEventListener('mousedown', onDocumentMouseDown, false);
function onDocumentMouseDown(event) {
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
event.preventDefault();
console.info("Click.");
// update the mouse variable
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// find intersections
// create a Ray with origin at the mouse position
// and direction into the scene (camera direction)
var vector = new THREE.Vector3(mouse.x, mouse.y, 1);
projector.unprojectVector(vector, camera);
var ray = new THREE.Raycaster();
ray.setFromCamera(mouse, camera);
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects(targetList);
// if there is one (or more) intersections
if (intersects.length > 0 && INTERSECTED != intersects[0].object) {
INTERSECTED = intersects[0].object;
INTERSECTED.material.emissive.setHex(0xff0000);
console.info(INTERSECTED.name);
// console.info("Hit @ " + toString( intersects[0].point ) );
// change the color of the closest face.
// intersects[ 0 ].face.color.setHex(0xffa500);
// intersects[ 0 ].object.geometry.colorsNeedUpdate = true;
for (var i = 0; i < targetList.length; i++) {
if (INTERSECTED.name == i) {
targetListBool[i] = true;
}
}
console.info(targetListBool);
}
}
// $(intersec).click(function(){
// alert('you clicked number 1 block');
// });
function toString(v) {
return "[ " + v.x + ", " + v.y + ", " + v.z + " ]";
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
}
function render() {
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
}
for (let i = 0; i <targetListBool.length ; i+=4) {
if (targetListBool[i]
&&targetListBool[i+1]
&&targetListBool[i+2]
&&targetListBool[i+3]){
alert('win');
}
}
<!DOCTYPE html>
<html lang = "en">
<head>
<title>Tic tac toe</title>
<meta charset = "utf-8">
<meta name = "viewport" content = "width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
.info {
position: absolute;
background-color: black;
opacity: 0.8;
color: white;
text-align: center;
top: 0px;
width: 100%;
}
.info a {
color: #00ffff;
}
button {
display: hidden;
}
</style>
</head>
<body>
<div id = "container">
<div>
<!-- <button id = "restart">Restart</button> -->
</div>
</div>
<script src = "https://ajax.googleapis.com/ajax/libs/threejs/r84/three.min.js"></script>
<script src = "https://rawgit.com/mrdoob/three.js/master/examples/js/controls/TrackballControls.js"></script>
<script src = "https://rawgit.com/mrdoob/three.js/master/examples/js/utils/BufferGeometryUtils.js"></script>
<script src = "https://rawgit.com/mrdoob/three.js/master/examples/js/libs/dat.gui.min.js"></script>
<script src = "https://rawgit.com/mrdoob/three.js/master/examples/js/renderers/Projector.js"></script>
</body>
</html>
Сейчас я пытаюсь проверить только горизонтальную выигрышную комбинацию для стартера.
for (let i = 0; i <targetListBool.length ; i+=4) {
if (targetListBool[i]
&&targetListBool[i+1]
&&targetListBool[i+2]
&&targetListBool[i+3]){
alert('win');
}
}
Но он не знает, что некоторые значения изменились из-за события клика раньше. Чтобы уточнить, он должен предупреждать "выигрыш", если щелкнуть 4 последовательных горизонтальных блока в каждой плоскости. но я думаю, что что-то не так с оператором if в цикле for в конце фрагмента.
Я впервые использую три js, и я тоже плохо знаком с javaScript. Буду признателен за любую помощь. Спасибо.
Ваш фрагмент работает для меня.
@LloydNicholson Я выложил фрагмент кода, спасибо!
@MarkBaijens Правда? Он должен предупреждать "победа", но это не ...! Мне удалось превратить нажатый элемент в массиве в true с событием, но я застрял в этом месте ..
@ Prisoner849 спасибо, я поправил.
@JessicaKim хорошо, что журнал показывает значение true, поэтому массив правильный. Но когда вы делаете горизонтальную линию, вы получаете 4 логических значения на истинном бите, которые не идут друг за другом. Вот почему ваш чек не проходит. Лучше отойти от стандартного массива и использовать какой-то метод, чтобы отслеживать их в трехмерном виде.
Ваша система выигрывает, если она имеет 4 подряд на оси x, y или z. Ваша функция проверяет только логические значения в одном направлении. Поэтому лучше всего отслеживать данные в трехмерном виде. Вот пример этого. Я вручную установил 4 в ряд по оси z, а затем провожу проверку.
Однако проверку можно и нужно улучшить. Это довольно неэффективно, но упрощено для примера и потому, что я не знаю ваших точных намерений. Стоит ли, например, проверить и диагонали?
//Fill a variable with x,y,z coordinates with a boolean value that is false.
var locations = {};
for (var x = 1; x <= 4; x++) {
locations[x] = {};
for (var y = 1; y <= 4; y++) {
locations[x][y] = {};
for (var z = 1; z <= 4; z++) {
locations[x][y][z] = false;
}
}
}
//Set 4 values on the X axis to true for testing
locations[1][2][3] = true;
locations[2][2][3] = true;
locations[3][2][3] = true;
locations[4][2][3] = true;
//Set 4 values on the Z axis to true for testing
locations[1][2][1] = true;
locations[1][2][2] = true;
locations[1][2][3] = true;
locations[1][2][4] = true;
//Test if there are 4 on a row - note this can be done more efficient with a bit more thought and does not work for diagonals
var winX = false;
var winY = false;
var winZ = false;
for (var x = 1; x <= 4; x++) {
for (var y = 1; y <= 4; y++) {
for (var z = 1; z <= 4; z++) {
if (locations[x][y][z]) {
//check X for current position
if (locations[1][y][z] && locations[2][y][z] && locations[3][y][z] && locations[4][y][z]) {
winX = true;
}
//check Y for current position
if (locations[x][1][z] && locations[x][2][z] && locations[x][3][z] && locations[x][4][z]) {
winY = true;
}
//check Z for current position
if (locations[x][y][1] && locations[x][y][2] && locations[x][y][3] && locations[x][y][4]) {
winZ = true;
}
}
}
}
}
//Log the results, should return true for X and Z and false for Y
console.info("Win X: " + winX);
console.info("Win Y: " + winY);
console.info("Win Z: " + winZ);
Изменен массив на объект, чтобы исправить ошибку с индексацией массива и сделать код чище.
Я исправил свою проблему, это было потому, что средство проверки выигрыша не было в функции щелчка. Спасибо за идею трехмерного массива, но я обязательно преобразовываю свой код в трехмерные массивы!
Не могли бы вы добавить свой html-файл и создать фрагмент в вопросе SO.