Skip to content
Snippets Groups Projects
Commit ea14e36f authored by Wade Fagen-Ulmschneider (waf)'s avatar Wade Fagen-Ulmschneider (waf)
Browse files

demo_tictactoe

parent c65dc1bf
No related branches found
No related tags found
No related merge requests found
{
"title": "Tic-tac-toe",
"index": 20170403,
"type": "Demo"
}
%% Cell type:markdown id: tags:
## Tic-tac-toe
Using graphs, we will explore the state space of a game of tic-tac-toe!
%% Cell type:code id: tags:
``` python
import networkx as nx
```
%% Cell type:code id: tags:
``` python
G = nx.DiGraph()
```
%% Cell type:code id: tags:
``` python
import json
with open("../res/tree.json", "w") as f:
from networkx.readwrite import json_graph
data = json_graph.tree_data(G, root=1)
json.dump(data, f, indent=2)
```
%% Cell type:code id: tags:
``` python
```
#
# See tictactoe.ipynb for the Python code!
#
%% Cell type:markdown id: tags:
## Tic-tac-toe
Using graphs, we will explore the state space of a game of tic-tac-toe!
%% Cell type:code id: tags:
``` python
import networkx as nx
```
%% Cell type:code id: tags:
``` python
G = nx.DiGraph()
```
%% Cell type:code id: tags:
``` python
import json
with open("../res/tree.json", "w") as f:
from networkx.readwrite import json_graph
data = json_graph.tree_data(G, root=1)
json.dump(data, f, indent=2)
```
%% Cell type:code id: tags:
``` python
```
{% extends "templates/projectBase.html" %}
{% block projectContent %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
<script src="web/vis.js"></script>
<div id="tree"></div>
<!--
<style>
.board {
padding-top: 25px;
padding-bottom: 70px;
width: 180px;
margin: 0px auto;
}
.board div
{
clear: both;
}
.board div span
{
text-align: center;
border-color: black;
border-style: solid;
width: 60px;
float: left;
height: 54px;
font-size: 36px;
font-weight: bold;
font-family: 'Courier New', Courier, 'Nimbus Mono L', monospace;
}
#cell_top_left { border-width: 0px 2px 2px 0px; }
#cell_top_center { border-width: 0px 2px 2px 2px; }
#cell_top_right { border-width: 0px 0px 2px 2px; }
#cell_middle_left { border-width: 2px 2px 2px 0px; }
#cell_middle_center { border-width: 2px 2px 2px 2px; }
#cell_middle_right { border-width: 2px 0px 2px 2px; }
#cell_bottom_left { border-width: 2px 2px 0px 0px; }
#cell_bottom_center { border-width: 2px 2px 0px 2px; }
#cell_bottom_right { border-width: 2px 0px 0px 2px; }
</style>
<h3 class="text-center">CS 205's tic-tac-toe</h3>
<h4 class="text-center" id="gameOver" style="display:none">
The game is over. <a href="?show=py_viz">Reset?</a>
</h4>
<div class="container" style="width: 180px; text-align: center;">
<div class="row">
<div class="board">
<div>
<span id="cell_top_left"></span>
<span id="cell_top_center"></span>
<span id="cell_top_right"></span>
</div>
<div>
<span id="cell_middle_left"></span>
<span id="cell_middle_center"></span>
<span id="cell_middle_right"></span>
</div>
<div>
<span id="cell_bottom_left"></span>
<span id="cell_bottom_center"></span>
<span id="cell_bottom_right"></span>
</div>
</div>
</div>
</div>
<hr />
<script>
show_trees = function() {
$("#div_show").hide();
$("#div_tree").show();
visualize(_tree, "#tree");
visualize(_bfs, "#tree_bfs");
visualize(_dfs, "#tree_dfs");
}
</script>
<div id="div_show" class="text-center">
<button onclick="show_trees()" type="button" class="btn btn-primary">Show State Trees</button>
</div>
<div id="div_tree" style="display: none">
<h3>All Valid States</h3>
<p>
The first tree shows every possible state that this game may reach, not
accounting for any intelligence from the human or the computer.
</p>
<div id="tree"></div>
<h3>Depth-First Search</h3>
<p>
This second tree shows an evaluation of the game state using a depth-first
search, pruning paths once a state where a win can be reached when a player
makes the optimal move.
</p>
<div id="tree_dfs"></div>
<h3>Breath-First Search</h3>
<p>
This final tree shows an evaluation of the game state using a breath-first
search, pruning paths once a state where a win can be reached when a player
makes the optimal move.
</p>
<div id="tree_bfs"></div>
</div>
-->
{% endblock %}
$(function() {
$.getJSON("res/tree.json")
.done(function (data) { visualize(data, "#tree"); })
.fail(function() { alert("Falied to load JSON!"); });
});
var redirectFunction = function(board) {
return function() {
window.location.replace("?show=py_viz&board=" + board);
};
};
var init = function(gameData) {
var id_map = [
"#cell_top_left", "#cell_top_center", "#cell_top_right",
"#cell_middle_left", "#cell_middle_center", "#cell_middle_right",
"#cell_bottom_left", "#cell_bottom_center", "#cell_bottom_right"
];
var move = gameData.current;
var game = gameData.game;
if (game == "finished") {
$("#gameOver").show();
}
if (game == "new") {
$("#div_show").hide();
}
for (var i = 0; i < 9; i++) {
if (move[i] == "X" || move[i] == "O") {
$(id_map[i]).html(move[i]);
} else if (game != "finished") {
var newBoard = move.slice(0);
newBoard[i] = "O";
board = newBoard.join("");
$(id_map[i]).click(redirectFunction(board))
.css("cursor", "pointer");
}
}
};
var visualize = function(data, target) {
// == BOILERPLATE ==
var margin = { top: 0, right: 50, bottom: 0, left: 50 },
width = 1100 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// ==
var tree = d3.layout.tree()
.size([width, 1]);
var diagonal = d3.svg.diagonal();
var root = data;
var nodes = tree.nodes(root);
// Re-calculate y
var yGivenDepth = function (depth) {
var base = 100;
var separation = 30;
var y = 0;
for (var i = 0; i < depth; i++) {
y += (base / (i + 1)) + separation;
}
return y;
};
var maxDepth = d3.max(nodes, function(d) { return d.depth; });
var height = yGivenDepth(maxDepth + 1);
nodes.forEach(function (d) {
d.y = yGivenDepth(d.depth);
});
var links = tree.links(nodes);
var svg = d3.select(target)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("width", width + margin.left + margin.right)
.style("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var drawBoard = function(d) {
var svg = d3.select(this);
var w = 100 / (d.depth + 1);
var board = svg.append("g")
.attr("transform", function (d) { return "translate(" + (d.x - (w/2)) + "," + d.y + ")" })
var grid = board.append("g");
grid.append("line").attr("x1", 0).attr("y1", w/3).attr("x2", w).attr("y2", w/3).attr("stroke", "black");
grid.append("line").attr("x1", 0).attr("y1", 2*w/3).attr("x2", w).attr("y2", 2*w/3).attr("stroke", "black");
grid.append("line").attr("y1", 0).attr("x1", w/3).attr("y2", w).attr("x2", w/3).attr("stroke", "black");
grid.append("line").attr("y1", 0).attr("x1", 2*w/3).attr("y2", w).attr("x2", 2*w/3).attr("stroke", "black");
for (var i = 0; i < 9; i++) {
var p = d.board[i];
var row = Math.floor(i / 3);
var col = i % 3;
var dx = (col * w/3) + (0.1 * w/3);
var dy = (row * w/3) + (0.1 * w/3);
var mark = board.append("g")
.attr("transform", function (d) { return "translate(" + dx + "," + dy + ")" });
if (p == "X") {
mark.append("line")
.attr("x1", 0).attr("y1", 0)
.attr("x2", 0.8*w/3).attr("y2", 0.8*w/3)
.attr("stroke", "red");
mark.append("line")
.attr("x1", 0).attr("y1", 0.8*w/3)
.attr("x2", 0.8*w/3).attr("y2", 0)
.attr("stroke", "red");
} else if (p == "O") {
mark.append("circle")
.attr("r", 0.4 * w/3)
.attr("cx", 0.4 * w/3)
.attr("cy", 0.4 * w/3)
.attr("stroke", "green")
.attr("stroke-width", 1)
.attr("fill", "transparent");
}
if (d.score == 1) {
board.append("line")
.attr("x1", 0.1*w).attr("y1", 0.1*w)
.attr("x2", 0.9*w).attr("y2", 0.9*w)
.attr("stroke", "red")
.attr("stroke-width", 3);
board.append("line")
.attr("x1", 0.1*w).attr("y1", 0.9*w)
.attr("x2", 0.9*w).attr("y2", 0.1*w)
.attr("stroke", "red")
.attr("stroke-width", 3);
} else if (d.score == -1) {
board.append("circle")
.attr("cx", w*0.5)
.attr("cy", w*0.5)
.attr("r", w*0.4)
.attr("fill", "transparent")
.attr("stroke", "green")
.attr("stroke-width", 3);
}
}
};
svg.selectAll("nodes")
.data(nodes)
.enter()
.append("g")
.each(drawBoard)
;
svg.selectAll("links")
.data(links)
.enter()
.append("path")
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "transparent")
.attr("d", function (d) {
//console.log(d);
var s = {
x: d.source.x,
y: d.source.y + (100 / (d.source.depth + 1)),
};
var t = {
x: d.target.x,
y: d.target.y,
};
return diagonal({
source: s,
target: t
});
})
;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment