我正在开发一个JS connect-four游戏。我的'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)。如何修改它以便它返回一个带有获胜计数器坐标的数组,而不仅仅是一条警告信息?我很欣赏最好的解决方案可能涉及放弃我原来的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)返回[[0,0],[0,1],[0,2],[0,3]];
答案 0 :(得分:1)
这是一个简单的解决方案:
winAlert
应该返回一个号码,例如1表示A,-1表示B check
函数都会检查此结果,如果它是-1或1,那么它将插入检查的值check
方法返回未定义的内容,即带有答案的数组,则不应进行其他检查state
持有谁赢了(-1, 1 or undefined
),如果有人赢了,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>');
答案 1 :(得分:1)
我现在看到已经有了答案。我想我应该早点回到这里。我一直在JSFiddle中研究这个版本。请参阅游戏的有用(尽管简单)版本的链接:http://jsfiddle.net/42tfrsva/2/
这不是游戏物理版本的表示,您必须从底部开始并逐步完成游戏。但是,在任何一种情况下,“checkScore()”方法都是相同的,以便扫描棋盘获胜。在这种情况下,该方法返回构成该行的复选框元素,但也可以很容易地修改它以返回每个单元格的坐标。
代码 - 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
方法的每个循环中,行/列循环仅限于获取垂直,水平和对角线所需的单元格。