/* information in each game tree node */
var node_size = 17; // number of elements of each game tree node
var slot_node_id = 0;
var slot_node_level = 1;
var slot_number_childs = 2;
var slot_id_first_child = 3;
var slot_value = 4;
var slot_x_pos = 5;
var slot_y_pos = 6;
var slot_alpha = 7;
var slot_beta = 8;
var slot_node_id_parent = 9;
var slot_current_child = 10;
var slot_best_child = 11;
/* tree information */
var gameTreeArray; // array having the game tree
var tree_height; // game tree height
var tree_number_nodes; // total number of nodes
/* draw parameters */
var tx=17; // triangle size_x = 2*tx
var ty=17; // triangle size_y = 2*ty
/* simulation parameters */
var setinterval_id;
var current_node_id=0;
var previous_node_id=-1;
var returned_child_value=0;
var step_minimax=0; // current step of algorithm
var simulation_mode=0; // 0-stop; 1-animated simulation; 2-step-by-step simulation
// constants
var MINUS_INFINITY = -1000; // or -Number.MAX_VALUE;
var PLUS_INFINITY = +1000;
var simulation_cycle = 800; // cycle time (ms)
/* draws node shape and changes node color to white*/
function draw_node(context, idx_node, fill_color) {
var cx = gameTreeArray[idx_node + slot_x_pos];
var cy = gameTreeArray[idx_node + slot_y_pos];
context.fillStyle = fill_color;
if (gameTreeArray[idx_node + slot_node_level] % 2 == 0) { // draw max player triangle node
context.beginPath();
context.moveTo(cx, cy-ty);
context.lineTo(cx-tx, cy+ty);
context.lineTo(cx+tx, cy+ty);
context.lineTo(cx, cy-ty);
context.stroke();
context.fill();
context.closePath();
var yy = cx - tx*8 - 25;
context.fillStyle = "black";
var oldFont=context.font;
context.font="6pt Arial";
context.font=oldFont;
if (gameTreeArray[idx_node+slot_number_childs]>0) {
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
x.setAttribute("value", "");
x.setAttribute("placeholder", "a");
x.style.left=yy+"px";
x.style.top= cy-20+"px";
document.body.appendChild(x);
}
}
else { // draw min player triangle node
context.beginPath();
context.moveTo(cx, cy+ty);
context.lineTo(cx-tx, cy-ty);
context.lineTo(cx+tx, cy-ty);
context.lineTo(cx, cy+ty);
context.stroke();
context.fill();
context.closePath();
var yy = cx - tx*8 - 25;
context.fillStyle = "black";
var oldFont=context.font;
context.font="6pt Arial";
context.font=oldFont;
if (gameTreeArray[idx_node+slot_number_childs]>0) {
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
x.setAttribute("value", "");
x.setAttribute("placeholder", "b");
x.style.left=yy+"px";
x.style.top= cy-20+"px";
document.body.appendChild(x);
}
}
context.fillStyle = "black"; // controls text color
if (gameTreeArray[idx_node + slot_number_childs]==0) // draw value if is terminal node
context.fillText(gameTreeArray[idx_node + slot_value], cx-4, cy+ty+16);
}
function create_game_tree() {
if (simulation_mode==1) clearInterval(setinterval_id);
simulation_mode=0;
var stringToSplit = document.form1.treestructure.value;
var arrayOfStringsInnerNodes = stringToSplit.split(" ");
stringToSplit = document.form1.utilvalues.value;
var arrayOfStringsLeafNodes = stringToSplit.split(" ");
var len1=arrayOfStringsInnerNodes.length;
var len2=arrayOfStringsLeafNodes.length;
tree_number_nodes = len1 + len2; // total number of nodes
gameTreeArray = new Array(tree_number_nodes * node_size); // total size of the array
// first loads into the array the inner nodes
var dp=0; // node depth
if (len1>0) {
gameTreeArray[slot_node_level]=dp; // depth of root node
gameTreeArray[slot_node_id_parent]=-1; // parent id of root node
gameTreeArray[slot_alpha]=MINUS_INFINITY; // init alpha value of root node
gameTreeArray[slot_beta]=PLUS_INFINITY; // init beta value of root node
}
for (var i=0,j=0,id_first_child = 1; i < len1; i++, j+=node_size) {
gameTreeArray[j+slot_node_id] = i;
if (gameTreeArray[j+slot_node_level] % 2 == 0)
gameTreeArray[j+slot_value] = MINUS_INFINITY; // max player initial value
else
gameTreeArray[j+slot_value] = PLUS_INFINITY; // min player initial value
gameTreeArray[j+slot_current_child] = -1;
gameTreeArray[j+slot_number_childs] = parseInt(arrayOfStringsInnerNodes[i],10);
gameTreeArray[j+slot_id_first_child] = id_first_child;
dp = gameTreeArray[j+slot_node_level];
for (var child=0; child < gameTreeArray[j+slot_number_childs]; child++) {
gameTreeArray[(id_first_child+child)*node_size + slot_node_level] = dp+1; // depth of child
gameTreeArray[(id_first_child+child)*node_size + slot_node_id_parent] = i; // parent id
}
id_first_child += gameTreeArray[j+slot_number_childs];
}
// second loads into the array the leaf nodes (terminal nodes)
for (var i=0,j=len1*node_size; i < len2; i++, j+=node_size) {
gameTreeArray[j+slot_node_id] = i+len1;
gameTreeArray[j+slot_number_childs] = 0; // terminal/leaf node
gameTreeArray[j+slot_id_first_child] = -1; // because is a terminal/leaf node
gameTreeArray[j+slot_value] = parseInt(arrayOfStringsLeafNodes[i],10);
}
tree_height = dp+1;
prepare_draw_tree(len2);
draw_tree();
}
function prepare_draw_tree(numLeafNodes) {
var canvas = document.getElementById('canvasab');
var context = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
var top_margin_h = 30; // top margin defined for canvas
var bot_margin_h = 40; // botton margin defined for canvas
var h_util = h - top_margin_h - bot_margin_h;
for (var i=tree_number_nodes - numLeafNodes, j=1, idx_node=i*node_size; i<tree_number_nodes; i++, j++,
idx_node+=node_size) {
gameTreeArray[idx_node + slot_y_pos] = parseInt(top_margin_h + (h_util*gameTreeArray[idx_node + slot_node_level])/tree_height);
gameTreeArray[idx_node + slot_x_pos] = parseInt((w/(numLeafNodes+1))*j);
}
for (var i=tree_number_nodes - numLeafNodes - 1, idx_node=i*node_size; i>=0; i--, idx_node-=node_size) {
gameTreeArray[idx_node + slot_y_pos] = parseInt(top_margin_h + (h_util*gameTreeArray[idx_node + slot_node_level])/tree_height);
var fc_idx = gameTreeArray[idx_node + slot_id_first_child] * node_size;
var lc_idx = (gameTreeArray[idx_node + slot_id_first_child] + gameTreeArray[idx_node + slot_number_childs] - 1) * node_size;
gameTreeArray[idx_node + slot_x_pos] = (gameTreeArray[fc_idx + slot_x_pos] + gameTreeArray[lc_idx + slot_x_pos])/2;
}
}
function draw_tree() {
var canvas = document.getElementById('canvasab');
var context = canvas.getContext('2d');
canvas.width = canvas.width; // resets canvas
context.strokeStyle = '#000';
context.lineWidth = 1;
for (var i=0, idx_node=0; i<tree_number_nodes; i++, idx_node+=node_size)
draw_node(context, idx_node, "white");
// draw line segments
for (var i=0, idx_node=0; i<tree_number_nodes; i++, idx_node+=node_size) {
var id_first_child = gameTreeArray[idx_node+slot_id_first_child];
var number_childs = gameTreeArray[idx_node+slot_number_childs];
var bx = gameTreeArray[idx_node + slot_x_pos];
var by = gameTreeArray[idx_node + slot_y_pos] + ty;
for (var child=0; child < number_childs; child++) {
var ex = gameTreeArray[(id_first_child+child)*node_size + slot_x_pos];
var ey = gameTreeArray[(id_first_child+child)*node_size + slot_y_pos] - ty;
context.beginPath();
context.moveTo(bx, by);
context.lineTo(ex, ey);
context.stroke();
context.closePath();
}
}
}
<form name="form1" method="POST" class="smart-blue">
<h1>minimax game search algorithm with alpha-beta pruning
<br></h1>
<label>
<br>
Enter the game tree structure:
<input name="treestructure" type="text" size="50" value="3 3 3 3">
</label>
<br>
<label>
<br>
Enter the game tree terminal values:
<input name="utilvalues" type="text" size="50" value="3 12 8 2 4 6 14 5 2">
</label>
<br>
<br>
<button type="button" value="Change game tree" onclick="create_game_tree()" name="definetree" class="button">
Create new game tree
</button>
<br>
<br>
</form>
<canvas id="canvasab" width="900" height="600">
Your browser does not support HTML5 Canvas!
</canvas>
我有这个代码将创建一个树,并与树一起根据树中的节点数(叶节点除外)生成一个输入框现在我想要的是我怎么做每个节点的每个输入框,如第一个输入框用于第一个节点,第二个输入框用于第二个节点,它就像那样
因为我想添加一个检查答案butoon来检查输入框值是否等于节点值并且这样做,输入框必须有id来引用特定节点或类似的东西,以便它可以正确检查
输入框是在javascript中创建的,而不是在html上。
我希望你们明白我的意思。 运行代码片段来查看。抱歉长代码。
我将不胜感激,谢谢。