JSFiddle - React, Tailwind, and code Playground

by bgmort

HTML

<h1>RoboTacToe</h1>
	Team 1:
	<select data-team="1" id="team1Type">
		<option selected value="random">Random</option>
		<option value="sequential">Sequential</option>
		<option value="empty">Empty</option>
	</select>
	<div>
	<textarea name="" id="team1Code" cols="50" rows="20"></textarea>
	</div>

	Team 2:
	<select data-team="2" id="team2Type">
		<option value="random">Random</option>
		<option selected value="sequential">Sequential</option>
		<option value="empty">Empty</option>
	</select>
	<div>
	<textarea name="" id="team2Code" cols="50" rows="20"></textarea>
	</div>

	<p>Results are logged in the console, for now.</p>

	<button id="playButton">Play</button>
	<button id="play1000Button">Play 1000 Games</button>


	<div id="board">
		<div id="r0" class="row r0">
			<div id="c1" class="cell c0"></div>
			<div id="c2" class="cell c1"></div>
			<div id="c3" class="cell c2"></div>
		</div>
		<div id="r1" class="row r1">
			<div id="c4" class="cell c0"></div>
			<div id="c5" class="cell c1"></div>
			<div id="c6" class="cell c2"></div>
		</div>
		<div id="r2" class="row r2">
			<div id="c7" class="cell c0"></div>
			<div id="c8" class="cell c1"></div>
			<div id="c9" class="cell c2"></div>
		</div>
	</div>

CSS

#board {
	margin: 10px;
	width: 470px;
	height: 470px;
}

.cell {
	width: 150px;
	height: 150px;
	float: left;
}

.cell:not(:last-child) {
	border-right: 10px solid black;
}

.row:not(:last-child) .cell {
	border-bottom: 10px solid black;
}

JavaScript

(() => {
	'use strict';
  
  var fakeConsole = {
  	log: console.log,
    error: console.error,
  };
  
  var noOp = () => {};
  var noOpConsole = {
    log: noOp,
    error: noOp,
  };

	//keep the scope separate so they can't touch any of our functions
	function createRunner(codeStr, console) {
		return new Function('console', '"use strict";' + codeStr + '\n;; return nextMove')(console);
	}

	//generate the lines
	var possibleLines = [
		[0, 0, 1, 0], //across 1
		[0, 1, 1, 0], //across 2
		[0, 2, 1, 0], //across 3
		[0, 0, 0, 1], //down 1
		[1, 0, 0, 1], //down 2
		[2, 0, 0, 1], //down 3
		[0, 0, 1, 1], //diagonal
		[2, 0, -1, 1], //reverse diagonal
	]
	.map(def => [
		{ row: def[0], col: def[1] },
		{ row: def[0] + def[2], col: def[1] + def[3] },
		{ row: def[0] + def[2] * 2, col: def[1] + def[3] * 2 },
	]);
	
	window.possibleLines = possibleLines;
	
	var xSvg = `
<svg view-box="0 0 150 150" width="150" height="150">
  <line x1="20" y1="20" x2="130" y2="130" stroke="red" stroke-width="15px" />
  <line x1="20" y1="130" x2="130" y2="20" stroke="red" stroke-width="15px" />
</svg>`;

   var oSvg = `
<svg view-box="0 0 150 150" width="150" height="150">
  <circle cx="50%" cy="50%" r="55" stroke="blue" fill="none" stroke-width="15px"/>
</svg>`;

	var Board = {
		getSpace: function(board, space) {
			return board[space.row][space.col];
		},
		checkSpace: function(board, space) {
			return !board[space.row][space.col];
		},
		applyMove: function(board, space, teamNum) {
			var newBoard = Board.copy(board);
			newBoard[space.row][space.col] = teamNum;
			return newBoard;
		},
		copy: function(board) {
			return [
				board[0].slice(),
				board[1].slice(),
				board[2].slice(),
			];
		},
		'new': function() {
			return [
				[0, 0, 0],
				[0, 0, 0],
				[0, 0, 0],
			];
		},
		validateSpace: function(space) {
			return (
				space &&
				Math.min(space.row, space.col) >= 0 &&
				Math.max(space.row, space.col) <= 2
			);
		},
		findWinner: function(board) {
			for...