Spaces:
Running
Running
Update index.html
Browse files- index.html +186 -22
index.html
CHANGED
@@ -1,24 +1,188 @@
|
|
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
+
|
4 |
+
<head>
|
5 |
+
<title>Connect-4 game</title>
|
6 |
+
</head>
|
7 |
+
|
8 |
+
<body>
|
9 |
+
<p style="user-select: none; font-family: sans-serif;">
|
10 |
+
Try to connect four stones in a row, a column, or a diagonal.
|
11 |
+
</p>
|
12 |
+
<p><button type="button" style="user-select: none;" id="ai-first">AI goes first</button></p>
|
13 |
+
<canvas id="game-board" width="600px" height="600px"></canvas>
|
14 |
+
<script>
|
15 |
+
function BoardGame(num_rows, num_cols) {
|
16 |
+
this.num_cols = num_cols;
|
17 |
+
this.num_rows = num_rows;
|
18 |
+
var this_ = this;
|
19 |
+
this.canvas_ctx = document.getElementById("game-board").getContext("2d");
|
20 |
+
this.board_scale = 30;
|
21 |
+
document.getElementById("game-board").height = this.board_scale * (num_rows + 1);
|
22 |
+
document.getElementById("game-board").width = this.board_scale * (num_cols + 1);
|
23 |
+
this.canvas_ctx.scale(this.board_scale, this.board_scale);
|
24 |
+
this.canvas_ctx.translate(1, 1);
|
25 |
+
this.reset = function () {
|
26 |
+
this.board = new Array(num_rows * num_cols);
|
27 |
+
for (let i = 0; i < this.board.length; i++) this.board[i] = 0;
|
28 |
+
this.mouse_x = -1;
|
29 |
+
this.mouse_y = -1;
|
30 |
+
this.who_play = 1;
|
31 |
+
this.ai_player = -1;
|
32 |
+
this.game_ended = false;
|
33 |
+
};
|
34 |
+
this.reset();
|
35 |
+
this.render_text = function (text) {
|
36 |
+
this.canvas_ctx.fillStyle = "black";
|
37 |
+
this.canvas_ctx.font = '1px monospace';
|
38 |
+
this.canvas_ctx.fillText(text, 1, 1);
|
39 |
+
};
|
40 |
+
this.submit_board = async function () {
|
41 |
+
document.body.style.cursor = 'progress';
|
42 |
+
const response = await fetch("submit", {
|
43 |
+
method: 'POST',
|
44 |
+
mode: 'cors', // no-cors, *cors, same-origin
|
45 |
+
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
46 |
+
credentials: 'same-origin', // include, *same-origin, omit
|
47 |
+
headers: { 'Content-Type': 'application/json' },
|
48 |
+
redirect: 'follow', // manual, *follow, error
|
49 |
+
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
|
50 |
+
body: JSON.stringify({ "board": this_.board, "ai-player": this_.ai_player }) // body data type must match "Content-Type" header
|
51 |
+
});
|
52 |
+
return response.json(); // parses JSON response into native JavaScript objects
|
53 |
+
}
|
54 |
+
this.end_game = function () {
|
55 |
+
this.game_ended = true;
|
56 |
+
setTimeout(function() {this_.reset();}, 3000);
|
57 |
+
};
|
58 |
+
this.ai_play = function() {
|
59 |
+
this_.submit_board().then(
|
60 |
+
function (info) {
|
61 |
+
document.body.style.cursor = 'default';
|
62 |
+
console.log(info);
|
63 |
+
let x = info["action"];
|
64 |
+
if (x != -1) {
|
65 |
+
let [_, y] = this_.get_candidate(x);
|
66 |
+
let i = y * this_.num_cols + x;
|
67 |
+
this_.board[i] = this_.who_play;
|
68 |
+
this_.who_play = -this_.who_play;
|
69 |
+
this_.render();
|
70 |
+
}
|
71 |
+
if (info["terminated"] == true) {
|
72 |
+
this_.end_game();
|
73 |
+
}
|
74 |
+
}
|
75 |
+
).catch(function (e) { });
|
76 |
+
};
|
77 |
+
document.getElementById("ai-first").onclick = function() {
|
78 |
+
this_.reset();
|
79 |
+
this_.ai_player = 1;
|
80 |
+
this_.ai_play();
|
81 |
+
};
|
82 |
+
document.getElementById("game-board").addEventListener('click', function (e) {
|
83 |
+
var rect = this.getBoundingClientRect();
|
84 |
+
var x = e.clientX - rect.left;
|
85 |
+
var y = e.clientY - rect.top;
|
86 |
+
var loc_x = Math.floor(x / this_.board_scale - 0.5);
|
87 |
+
var loc_y = Math.floor(y / this_.board_scale - 0.5);
|
88 |
+
this_.mouse_x = loc_x;
|
89 |
+
this_.mouse_y = this_.get_candidate(this_.mouse_x)[1];
|
90 |
+
|
91 |
+
if (
|
92 |
+
this_.mouse_x >= 0 &&
|
93 |
+
this_.mouse_y >= 0 &&
|
94 |
+
this_.mouse_x < this_.num_cols &&
|
95 |
+
this_.mouse_y < this_.num_rows &&
|
96 |
+
this_.game_ended == false
|
97 |
+
) {
|
98 |
+
if (this_.who_play == this_.ai_player) return false;
|
99 |
+
let i = this_.mouse_y * this_.num_cols + this_.mouse_x;
|
100 |
+
if (this_.board[i] != 0) return false;
|
101 |
+
this_.board[i] = this_.who_play;
|
102 |
+
this_.who_play = -this_.who_play;
|
103 |
+
this_.render();
|
104 |
+
this_.ai_play();
|
105 |
+
}
|
106 |
+
}, false);
|
107 |
+
this.draw_stone = function (x, y, color) {
|
108 |
+
let ctx = this.canvas_ctx;
|
109 |
+
y = this.num_rows - 1 - y;
|
110 |
+
ctx.beginPath();
|
111 |
+
ctx.arc(x, y, 0.40, 0, 2 * Math.PI, false);
|
112 |
+
ctx.fillStyle = color;
|
113 |
+
ctx.fill();
|
114 |
+
ctx.lineWidth = 0.02;
|
115 |
+
ctx.strokeStyle = "black";
|
116 |
+
ctx.stroke();
|
117 |
+
};
|
118 |
+
this.get_candidate = function (x) {
|
119 |
+
for (let i = 0; i < this.num_rows; i++) {
|
120 |
+
let idx = i * this.num_cols + x;
|
121 |
+
if (this.board[idx] == 0) return [x, i];
|
122 |
+
}
|
123 |
+
return [-1, -1];
|
124 |
+
};
|
125 |
+
this.render = function () {
|
126 |
+
let ctx = this.canvas_ctx;
|
127 |
+
ctx.fillStyle = "#b8891c";
|
128 |
+
ctx.fillRect(-1, -1, num_cols + 1, num_rows + 1);
|
129 |
+
ctx.fillStyle = "#b8891c";
|
130 |
+
ctx.fillRect(0, 0, num_cols - 1, num_rows - 1);
|
131 |
+
ctx.lineWidth = 0.1 / 5;
|
132 |
+
for (let i = 0; i < this.num_cols; i++) {
|
133 |
+
ctx.beginPath();
|
134 |
+
ctx.moveTo(i, 0);
|
135 |
+
ctx.lineTo(i, this.num_rows - 1);
|
136 |
+
ctx.strokeStyle = "black";
|
137 |
+
ctx.stroke();
|
138 |
+
}
|
139 |
+
for (let i = 0; i < this.num_rows; i++) {
|
140 |
+
ctx.beginPath();
|
141 |
+
ctx.moveTo(0, i);
|
142 |
+
ctx.lineTo(this.num_cols - 1, i);
|
143 |
+
ctx.strokeStyle = "black";
|
144 |
+
ctx.stroke();
|
145 |
+
}
|
146 |
+
for (let i = 0; i < this.board.length; i++) {
|
147 |
+
let x = i % this.num_cols;
|
148 |
+
let y = Math.floor(i / this.num_cols);
|
149 |
+
if (this.board[i] == 0) continue;
|
150 |
+
let color = (this.board[i] == 1) ? "#3a352d" : "#f0ece4";
|
151 |
+
this.draw_stone(x, y, color);
|
152 |
+
}
|
153 |
+
if (
|
154 |
+
this.mouse_x >= 0 &&
|
155 |
+
this.mouse_y >= 0 &&
|
156 |
+
this.mouse_x < this.num_cols &&
|
157 |
+
this.mouse_y < this.num_rows
|
158 |
+
) {
|
159 |
+
let [x, y] = this.get_candidate(this.mouse_x);
|
160 |
+
if (x == -1) return;
|
161 |
+
this.mouse_x = x;
|
162 |
+
this.mouse_y = y;
|
163 |
+
if (this.who_play == -1)
|
164 |
+
this.draw_stone(x, y, "#bda051");
|
165 |
+
else
|
166 |
+
this.draw_stone(x, y, "#6d6051");
|
167 |
+
}
|
168 |
+
};
|
169 |
+
document.getElementById("game-board").onmousemove = function (e) {
|
170 |
+
// important: correct mouse position:
|
171 |
+
var rect = this.getBoundingClientRect();
|
172 |
+
var x = e.clientX - rect.left;
|
173 |
+
var y = e.clientY - rect.top;
|
174 |
+
var loc_x = Math.floor(x / this_.board_scale - 0.5);
|
175 |
+
var loc_y = Math.floor(y / this_.board_scale - 0.5);
|
176 |
+
this_.mouse_x = loc_x;
|
177 |
+
this_.mouse_y = loc_y;
|
178 |
+
setTimeout(function () { this_.render(); });
|
179 |
+
};
|
180 |
+
};
|
181 |
+
document.addEventListener("DOMContentLoaded", function (event) {
|
182 |
+
game = new BoardGame(6, 7);
|
183 |
+
game.render();
|
184 |
+
});
|
185 |
+
</script>
|
186 |
+
</body>
|
187 |
+
|
188 |
+
</html>
|