Return 在 JS Connect-Four 中获胜的单元格坐标
Return winning cell coordinates in JS Connect-Four
我正在开发一款 JS 连连四游戏。我的 'board' 是一个 7 * 6 维数组(0 = 空,1 = 玩家 A 占用,-1 = 玩家 B 占用)。
var boardTwo = [[1,1,1,1,0,0],[-1,-1,-1,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]];
这是我的(冗长的)函数,用于检查获胜(任一玩家是否在棋盘上创建了一条完整的水平、垂直或对角线长度 4)。我如何修改它,使它 return 是一个包含获胜计数器坐标的数组,而不是简单的警报消息?我很欣赏最好的解决方案可能包括放弃我原来的 checkWin 函数来代替更简洁的函数。
checkWin = function(board){
checkVert(board);
checkHoriz(board);
checkDia(board);
}
winAlert = function(checkSum){
if(checkSum == 4){
status = "a"
alert("a wins");
}
else if(checkSum == -4){
status = 'b';
alert("b wins");
}
}
checkVert = function(board){
for(var i = 0; i < board.length; i++){
for(var j = 0; j < board[0].length - 3; j++){
var checkSum = board[i][j] + board[i][j+1] + board[i][j+2] + board[i][j+3];
winAlert(checkSum);
}
}
}
checkHoriz = function(board){
for(var i = 0; i < board.length-3; i++){
for(var j = 0; j < board[0].length; j++){
var checkSum = board[i][j] + board[i+1][j] + board[i+2][j] + board[i+3][j];
winAlert(checkSum);
}
}
}
checkDia = function(board){
for(var i = 0; i < board.length-3; i++){
for(var j = 0; j < board[0].length - 3; j++){
var checkSum = board[i][j] + board[i+1][j+1] + board[i+2][j+2] + board[i+3][j+3];
winAlert(checkSum);
}
}
}
checkWin(boardTwo) //alerts "player A wins"
我想要 checkWin(boardTwo) 到 return [[0,0],[0,1],[0,2],[0,3]];
这是一个简单的解决方案:
如果有人赢了,winAlert
应该 return 一个数字,例如A 为 1,B 为 -1
- 每个
check
函数都会检查这个结果,如果它是 -1 或 1,那么它将插入它检查的值
- 如果
check
方法 return 不是未定义的东西,即带有答案的数组,则不应进行其他检查
- 最后
state
保存谁赢了 (-1, 1 or undefined
) 并且 returning 值 checkWin
将是一个数组数组如果有人赢了
我还对 checkDiagonal
方法进行了额外检查,以检查矩阵中存在的其他对角线
function sgn(x) {
if (x < 0) return -1;
if (x > 0) return 1;
return 0;
}
function interpolate(from, to) {
var coordinates = [];
var startX = from[0];
var startY = from[1];
var limit = Math.max(
Math.abs(from[0] - to[0]),
Math.abs(from[1] - to[1])
) + 1;
for (i = 0; i < limit; i += 1) {
coordinates.push([
startX + i * sgn(to[0] - from[0]),
startY + i * sgn(to[1] - from[1])
]);
}
return coordinates;
}
var state;
function checkWin(board) {
var ans;
ans = ans || checkVert(board);
ans = ans || checkHoriz(board);
ans = ans || checkDia(board);
return ans;
}
function winAlert(checkSum) {
if (Math.abs(checkSum) === 4) {
state = sgn(checkSum);
return state;
}
}
checkVert = function(board) {
for (var i = 0; i < board.length; i++) {
for (var j = 0; j < board[0].length - 3; j++) {
var checkSum = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i][j + 3];
if (winAlert(checkSum)) {
return interpolate([i, j], [i, j + 3]);
}
}
}
}
checkHoriz = function(board) {
for (var i = 0; i < board.length - 3; i++) {
for (var j = 0; j < board[0].length; j++) {
var checkSum = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i + 3][j];
if (winAlert(checkSum)) {
return interpolate([i, j], [i + 3, j]);
}
}
}
}
checkDia = function(board) {
for (var i = 0; i < board.length - 3; i++) {
for (var j = 0; j < board[0].length - 3; j++) {
var checkSum = board[i][j] + board[i + 1][j + 1] + board[i + 2][j + 2] + board[i + 3][j + 3];
if (winAlert(checkSum)) {
return interpolate([i, j], [i + 3, j + 3]);
}
}
}
// missing diagonal
for (i = 3; i < board.length; i += 1) {
for (var j = 0; j < board[0].length - 3; j++) {
var checkSum = board[i][j] + board[i - 1][j + 1] + board[i - 2][j + 2] + board[i - 3][j + 3];
if (winAlert(checkSum)) {
return interpolate([i, j], [i - 3, j + 3]);
}
}
}
}
var board = [
[1, 1, 1, 0, 0, 0],
[-1, -1, -1, -1, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]
];
var ans = checkWin(board) || [];
document.write(state + '<pre>' + JSON.stringify(ans) + '</pre>');
我看到现在已经有答案了。我想我应该早点回来。我也一直在 JSFiddle 中研究这个版本。请参阅 link 以了解游戏的工作(虽然简单)版本:http://jsfiddle.net/42tfrsva/2/
这不是实体版游戏的代表,您必须从底部开始逐步向上。但是,“checkScore()”方法在任何一种情况下都将相同,以扫描棋盘以获取胜利。在这种情况下,方法 return 是组成该行的复选框元素,但它可以很容易地修改为 return 每个单元格的坐标。
代码 - HTML
<table>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
</table>
<div id="player">Player 1</div>
<button id="reset">Reset</button>
代码 - CSS
.player1 {
background-color: red;
}
.player2 {
background-color: blue;
}
.winner {
background-color: green;
}
代码 - JS
var player = 1;
//Set up check events
var cbs = checkboxes();
for (var t = 0; t < cbs.length; t++){
cbs[t].onclick = checkClick;
}
//Set up reset event
$id("reset").onclick = resetClick;
function resetClick() {
var cbs = checkboxes();
for (var c = 0; c < cbs.length; c++) {
cbs[c].checked = false;
cbs[c].value = 0;
cbs[c].parentNode.className = "";
}
player = 1;
$html("player", "Player 1");
}
//create functions
function $id(id) {
return document.getElementById(id);
}
function $tags(tag, parent) {
parent = (parent) ? parent : document;
return parent.getElementsByTagName(tag);
}
function $html(id, html) {
var el = $id(id);
if (el) el.innerHTML = html;
}
function checkboxes() {
var tags = $tags("input");
var cbs = [];
for (var t = 0; t < tags.length; t++) {
if (tags[t].type == "checkbox")
cbs.push(tags[t]);
}
return cbs;
}
function checkClick(e) {
if (!e || !e.target || !e.target.parentNode
|| e.target.value != "0") {
e.preventDefault();
return false;
}
e.target.parentNode.className = "player" + player;
e.target.value = player;
var path = checkScore();
if (path.length == 4) {
alert("Winner player " + player + "!");
for (var p = 0; p < path.length; p++)
path[p].parentNode.className = "winner";
}
player = (player == 1) ? 2 : 1;
$html("player", "Player " + player);
}
function valueArray() {
var values = [];
var cbs, trs = $tags("tr", $tags("table")[0]);
for (var t = 0; t < trs.length; t++) {
cbs = $tags("input", trs[t]);
var cbarr = [];
for (var c = 0; c < cbs.length; c++) {
cbarr.push(cbs[c].value*1);
}
values.push(cbarr);
}
return values;
}
function cbArray() {
var values = [];
var cbs, trs = $tags("tr", $tags("table")[0]);
for (var t = 0; t < trs.length; t++) {
cbs = $tags("input", trs[t]);
var cbarr = [];
for (var c = 0; c < cbs.length; c++) {
cbarr.push(cbs[c]);
}
values.push(cbarr);
}
return values;
}
function checkScore() {
var path = [];
var values = valueArray();
var cbs = cbArray();
//check up/down
for (var r = 0; r < 3; r++) {
for (var c = 0; c < 7; c++) {
if (values[r][c] == player && values[r+1][c] == player &&
values[r+2][c] == player && values[r+3][c] == player) {
path = new Array(
cbs[r][c], cbs[r+1][c],
cbs[r+2][c], cbs[r+3][c]
);
return path;
}
}
}
//check left/right
for (var r = 0; r < 6; r++) {
for (var c = 0; c < 4; c++) {
if (values[r][c] == player && values[r][c+1] == player &&
values[r][c+2] == player && values[r][c+3] == player) {
path = new Array(
cbs[r][c], cbs[r][c+1],
cbs[r][c+2], cbs[r][c+3]
);
return path;
}
}
}
//check right diagonal
for (var r = 0; r < 3; r++) {
for (var c = 0; c < 4; c++) {
if (values[r][c] == player && values[r+1][c+1] == player &&
values[r+2][c+2] == player && values[r+3][c+3] == player) {
path = new Array(
cbs[r][c], cbs[r+1][c+1],
cbs[r+2][c+2], cbs[r+3][c+3]
);
return path;
}
}
}
//check left diagonal
for (var r = 0; r < 3; r++) {
for (var c = 3; c < 7; c++) {
if (values[r][c] == player && values[r+1][c-1] == player &&
values[r+2][c-2] == player && values[r+3][c-3] == player) {
path = new Array(
cbs[r][c], cbs[r+1][c-1],
cbs[r+2][c-2], cbs[r+3][c-3]
);
return path;
}
}
}
return path;
}
我意识到您不必检查每个单元格。在 checkScore
方法的每个循环中,row/column 循环仅限于获取垂直线、水平线和对角线所需的单元格。
我正在开发一款 JS 连连四游戏。我的 'board' 是一个 7 * 6 维数组(0 = 空,1 = 玩家 A 占用,-1 = 玩家 B 占用)。
var boardTwo = [[1,1,1,1,0,0],[-1,-1,-1,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]];
这是我的(冗长的)函数,用于检查获胜(任一玩家是否在棋盘上创建了一条完整的水平、垂直或对角线长度 4)。我如何修改它,使它 return 是一个包含获胜计数器坐标的数组,而不是简单的警报消息?我很欣赏最好的解决方案可能包括放弃我原来的 checkWin 函数来代替更简洁的函数。
checkWin = function(board){
checkVert(board);
checkHoriz(board);
checkDia(board);
}
winAlert = function(checkSum){
if(checkSum == 4){
status = "a"
alert("a wins");
}
else if(checkSum == -4){
status = 'b';
alert("b wins");
}
}
checkVert = function(board){
for(var i = 0; i < board.length; i++){
for(var j = 0; j < board[0].length - 3; j++){
var checkSum = board[i][j] + board[i][j+1] + board[i][j+2] + board[i][j+3];
winAlert(checkSum);
}
}
}
checkHoriz = function(board){
for(var i = 0; i < board.length-3; i++){
for(var j = 0; j < board[0].length; j++){
var checkSum = board[i][j] + board[i+1][j] + board[i+2][j] + board[i+3][j];
winAlert(checkSum);
}
}
}
checkDia = function(board){
for(var i = 0; i < board.length-3; i++){
for(var j = 0; j < board[0].length - 3; j++){
var checkSum = board[i][j] + board[i+1][j+1] + board[i+2][j+2] + board[i+3][j+3];
winAlert(checkSum);
}
}
}
checkWin(boardTwo) //alerts "player A wins"
我想要 checkWin(boardTwo) 到 return [[0,0],[0,1],[0,2],[0,3]];
这是一个简单的解决方案:
-
如果有人赢了,
winAlert
应该 return 一个数字,例如A 为 1,B 为 -1- 每个
check
函数都会检查这个结果,如果它是 -1 或 1,那么它将插入它检查的值 - 如果
check
方法 return 不是未定义的东西,即带有答案的数组,则不应进行其他检查 - 最后
state
保存谁赢了 (-1, 1 or undefined
) 并且 returning 值checkWin
将是一个数组数组如果有人赢了
我还对 checkDiagonal
方法进行了额外检查,以检查矩阵中存在的其他对角线
function sgn(x) {
if (x < 0) return -1;
if (x > 0) return 1;
return 0;
}
function interpolate(from, to) {
var coordinates = [];
var startX = from[0];
var startY = from[1];
var limit = Math.max(
Math.abs(from[0] - to[0]),
Math.abs(from[1] - to[1])
) + 1;
for (i = 0; i < limit; i += 1) {
coordinates.push([
startX + i * sgn(to[0] - from[0]),
startY + i * sgn(to[1] - from[1])
]);
}
return coordinates;
}
var state;
function checkWin(board) {
var ans;
ans = ans || checkVert(board);
ans = ans || checkHoriz(board);
ans = ans || checkDia(board);
return ans;
}
function winAlert(checkSum) {
if (Math.abs(checkSum) === 4) {
state = sgn(checkSum);
return state;
}
}
checkVert = function(board) {
for (var i = 0; i < board.length; i++) {
for (var j = 0; j < board[0].length - 3; j++) {
var checkSum = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i][j + 3];
if (winAlert(checkSum)) {
return interpolate([i, j], [i, j + 3]);
}
}
}
}
checkHoriz = function(board) {
for (var i = 0; i < board.length - 3; i++) {
for (var j = 0; j < board[0].length; j++) {
var checkSum = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i + 3][j];
if (winAlert(checkSum)) {
return interpolate([i, j], [i + 3, j]);
}
}
}
}
checkDia = function(board) {
for (var i = 0; i < board.length - 3; i++) {
for (var j = 0; j < board[0].length - 3; j++) {
var checkSum = board[i][j] + board[i + 1][j + 1] + board[i + 2][j + 2] + board[i + 3][j + 3];
if (winAlert(checkSum)) {
return interpolate([i, j], [i + 3, j + 3]);
}
}
}
// missing diagonal
for (i = 3; i < board.length; i += 1) {
for (var j = 0; j < board[0].length - 3; j++) {
var checkSum = board[i][j] + board[i - 1][j + 1] + board[i - 2][j + 2] + board[i - 3][j + 3];
if (winAlert(checkSum)) {
return interpolate([i, j], [i - 3, j + 3]);
}
}
}
}
var board = [
[1, 1, 1, 0, 0, 0],
[-1, -1, -1, -1, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]
];
var ans = checkWin(board) || [];
document.write(state + '<pre>' + JSON.stringify(ans) + '</pre>');
我看到现在已经有答案了。我想我应该早点回来。我也一直在 JSFiddle 中研究这个版本。请参阅 link 以了解游戏的工作(虽然简单)版本:http://jsfiddle.net/42tfrsva/2/
这不是实体版游戏的代表,您必须从底部开始逐步向上。但是,“checkScore()”方法在任何一种情况下都将相同,以扫描棋盘以获取胜利。在这种情况下,方法 return 是组成该行的复选框元素,但它可以很容易地修改为 return 每个单元格的坐标。
代码 - HTML
<table>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
<tr>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
<td><input type="checkbox" value="0" /></td>
</tr>
</table>
<div id="player">Player 1</div>
<button id="reset">Reset</button>
代码 - CSS
.player1 {
background-color: red;
}
.player2 {
background-color: blue;
}
.winner {
background-color: green;
}
代码 - JS
var player = 1;
//Set up check events
var cbs = checkboxes();
for (var t = 0; t < cbs.length; t++){
cbs[t].onclick = checkClick;
}
//Set up reset event
$id("reset").onclick = resetClick;
function resetClick() {
var cbs = checkboxes();
for (var c = 0; c < cbs.length; c++) {
cbs[c].checked = false;
cbs[c].value = 0;
cbs[c].parentNode.className = "";
}
player = 1;
$html("player", "Player 1");
}
//create functions
function $id(id) {
return document.getElementById(id);
}
function $tags(tag, parent) {
parent = (parent) ? parent : document;
return parent.getElementsByTagName(tag);
}
function $html(id, html) {
var el = $id(id);
if (el) el.innerHTML = html;
}
function checkboxes() {
var tags = $tags("input");
var cbs = [];
for (var t = 0; t < tags.length; t++) {
if (tags[t].type == "checkbox")
cbs.push(tags[t]);
}
return cbs;
}
function checkClick(e) {
if (!e || !e.target || !e.target.parentNode
|| e.target.value != "0") {
e.preventDefault();
return false;
}
e.target.parentNode.className = "player" + player;
e.target.value = player;
var path = checkScore();
if (path.length == 4) {
alert("Winner player " + player + "!");
for (var p = 0; p < path.length; p++)
path[p].parentNode.className = "winner";
}
player = (player == 1) ? 2 : 1;
$html("player", "Player " + player);
}
function valueArray() {
var values = [];
var cbs, trs = $tags("tr", $tags("table")[0]);
for (var t = 0; t < trs.length; t++) {
cbs = $tags("input", trs[t]);
var cbarr = [];
for (var c = 0; c < cbs.length; c++) {
cbarr.push(cbs[c].value*1);
}
values.push(cbarr);
}
return values;
}
function cbArray() {
var values = [];
var cbs, trs = $tags("tr", $tags("table")[0]);
for (var t = 0; t < trs.length; t++) {
cbs = $tags("input", trs[t]);
var cbarr = [];
for (var c = 0; c < cbs.length; c++) {
cbarr.push(cbs[c]);
}
values.push(cbarr);
}
return values;
}
function checkScore() {
var path = [];
var values = valueArray();
var cbs = cbArray();
//check up/down
for (var r = 0; r < 3; r++) {
for (var c = 0; c < 7; c++) {
if (values[r][c] == player && values[r+1][c] == player &&
values[r+2][c] == player && values[r+3][c] == player) {
path = new Array(
cbs[r][c], cbs[r+1][c],
cbs[r+2][c], cbs[r+3][c]
);
return path;
}
}
}
//check left/right
for (var r = 0; r < 6; r++) {
for (var c = 0; c < 4; c++) {
if (values[r][c] == player && values[r][c+1] == player &&
values[r][c+2] == player && values[r][c+3] == player) {
path = new Array(
cbs[r][c], cbs[r][c+1],
cbs[r][c+2], cbs[r][c+3]
);
return path;
}
}
}
//check right diagonal
for (var r = 0; r < 3; r++) {
for (var c = 0; c < 4; c++) {
if (values[r][c] == player && values[r+1][c+1] == player &&
values[r+2][c+2] == player && values[r+3][c+3] == player) {
path = new Array(
cbs[r][c], cbs[r+1][c+1],
cbs[r+2][c+2], cbs[r+3][c+3]
);
return path;
}
}
}
//check left diagonal
for (var r = 0; r < 3; r++) {
for (var c = 3; c < 7; c++) {
if (values[r][c] == player && values[r+1][c-1] == player &&
values[r+2][c-2] == player && values[r+3][c-3] == player) {
path = new Array(
cbs[r][c], cbs[r+1][c-1],
cbs[r+2][c-2], cbs[r+3][c-3]
);
return path;
}
}
}
return path;
}
我意识到您不必检查每个单元格。在 checkScore
方法的每个循环中,row/column 循环仅限于获取垂直线、水平线和对角线所需的单元格。