我的jQuery作业有问题(我是学生和JS初学者)。
基本上,我的任务是使用MV(C)(我们不使用控制器)模式使用jQuery创建一个Connect 4游戏。
比赛场地是一个2D阵列,看起来像这样。
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
并且玩家按下列进行游戏(f.ex.Player 1按3)
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , x , - , - , - , -
并且播放器2按下4
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , - , - , - , - , -
- , - , x , o , - , - , -
等等。
当游戏结束时,获胜的四个字母应该变为大写。
我被困住了,并且真的不知道如何继续下去所以我创建了一个包含所有代码的GitHub存储库。
https://github.com/VeronicaLeeds/connectfour
基本上它初始化了比赛场地,你可以按数字,但是play()方法不会起作用。
如果有人能告诉我它为什么不将数组的值从 - 更改为x / o,那会很棒吗?
这是代码:
checkAvailableRow(column) {
for (var i = 5 ; i >= 0 ; i--) {
console.log(currentPlayer);
if (playFieldArray[column][i] === "-") {
return i;
if(currentPlayer == "Player 1"){
playFieldArray[column][i] = "x";
} else {
playFieldArray[column][i] = "o";
}
}
}
return -1;
}
为什么Model.js中的checkIfWon()函数不起作用。
永远感激任何帮助。
答案 0 :(得分:0)
return i;
返回会导致逻辑进程返回其所处的函数。因此,它之后的任何逻辑都不会发生。评论此声明并查看是否有任何变化(应该)。
或者将其移动到更改数组值的if / else之后。
答案 1 :(得分:0)
以下是在提供网格和x值时如何获得y轴的可用索引的示例:
//function to get available index for y when given grid and x
// it will return false if no y is available
const getY = (grid,index)=>{
const getIndex = (arr,index) => {
if(arr[index]==="-"){
return index;
}
if(index<0){
return false;
}
return getIndex(arr,index-1);
}
return getIndex(grid[index],grid[index].length-1);
}
//Run some tests:
const rotate = grid =>//just to make the grid look normal in console.log
grid[0].map((i,y)=>grid.map((i,x)=>[y,x]))
.map((row)=>row.map(([y,x])=>grid[x][y]));
const format = grid => rotate(grid).map(row=>row.join(" ")).join("\n");
//function to mutate grid setting items for testing
const setItem = (x,grid,value) => y => grid[x][y]=value;
//7 by 6 grid containing -
const grid = Array.from(new Array(7),()=>Array.from(new Array(6),()=>"-"));
//add some values to grid
[0,1,2,3,4,5].forEach(x=>[0,1,2,3,4,5].slice(x).forEach(setItem(x,grid,"O")));
console.log("grid is:");
console.log(format(grid));
//see the values for y when asking for
console.log("Testing....");
[0,1,2,3,4,5,6].forEach(
x=>console.log(`y is ${getY(grid,x)} when x is:${x}`)
);
以下是检查玩家是否在给定网格和位置的情况下获胜的功能。
const isWin = (grid,position) => {
const [x,y] = position;
const player = grid[x][y];
if(player==="-"){//current location in grid is empty, return false
return false;
}
const countConnectedAllDirections = (directions,position,player) => {
const connectCount = (direction,position,player,count=1)=>{
const [x,y]=[position[0]+count*direction[0],position[1]+count*direction[1]];
if((grid[x] && grid[x][y])!==player){
return count;
}
return connectCount(direction,position,player,count+1);
};
return directions.map(
([back,forward])=>[connectCount(back,position,player),forward]
).map(
([countBack,forward])=>[countBack,connectCount(forward,position,player)]
).map(
([countBack,countForward])=>countBack+countForward-1
).reduce(
(highest,item)=>(item>highest)?item:highest,0
);
}
const directions = [[0,-1],[-1,-1],[-1,0],[-1,1]].map(([x,y])=>[[x,y],[x*-1,y*-1]]);
return countConnectedAllDirections(directions,position,player)>=4;
};
//Run some tests:
const rotate = grid =>//just to make the grid look normal in console.log
grid[0].map((i,y)=>grid.map((i,x)=>[y,x]))
.map((row)=>row.map(([y,x])=>grid[x][y]));
const format = grid => rotate(grid).map(row=>row.join(" ")).join("\n");
const test = (message,pass) =>
(pass)
? console.log(`Passed: ${message}`)
: console.error(`Failed: ${message}`)
//function to mutate grid setting items for testing
const setItem = (x,y,value) => grid[x][y]=value;
//7 by 6 grid containing -
const createGrid = () => Array.from(new Array(7),()=>Array.from(new Array(6),()=>"-"));
var grid = createGrid();
test("Should return false when position is empty",isWin(grid,[0,5])===false);
const posReducer = (all,pos)=>all&&isWin(grid,pos);
[[0,5],[0,4],[0,3]].forEach(([x,y])=>setItem(x,y,"X"));
console.log(format(grid));
test(
"Should return false when position is not empty but not connect 4",
[[0,5],[0,4],[0,3]].reduce((all,pos)=>all||isWin(grid,pos),false)===false
);
[[0,5],[0,4],[0,3],[0,2]].forEach(([x,y])=>setItem(x,y,"X"));
console.log(format(grid));
test(
"Should return true when position is not empty and connect 4 vertical",
[[0,5],[0,4],[0,3],[0,2]].reduce(posReducer,true)
);
grid = createGrid();//reset grid
[[1,5],[2,5],[3,5],[4,5]].forEach(([x,y])=>setItem(x,y,"X"));
console.log(format(grid));
test(
"Should return true when position is not empty and connect 4 horizontal",
[[1,5],[2,5],[3,5],[4,5]].reduce(posReducer,true)
);
grid = createGrid();//reset grid
[[1,5],[2,4],[3,3],[4,2]].forEach(([x,y])=>setItem(x,y,"X"));
console.log(format(grid));
test(
"Should return true when position is not empty and connect 4 diagonal bottom left to top right",
[[1,5],[2,4],[3,3],[4,2]].reduce(posReducer,true)
);
grid = createGrid();//reset grid
[[1,2],[2,3],[3,4],[4,5]].forEach(([x,y])=>setItem(x,y,"X"));
console.log(format(grid));
test(
"Should return true when position is not empty and connect 4 diagonal top left to bottom right",
[[1,2],[2,3],[3,4],[4,5]].reduce(posReducer,true)
);
以下是完整的游戏:
//view part
const [init,paint] = (()=>{
const getStyle = gridValue =>
(gridValue==="-")
? ""
: `style="background-color:${(gridValue==="RED")?"red":"green"}"`;
const createTD = ([x,y,gridValue]) =>
`<td ${getStyle(gridValue)} data-role="turn" data-position="${x},${y}"></td>`;
const createTR = gridRow =>
`<tr>${gridRow.reduce((result,value)=>result+createTD(value),"")}</tr>`;
const createTable = grid =>
`<table>${
grid.reduce((all,row)=>all+createTR(row),"")
}</table>`
;
const createMessage = message => `<div><h1>${message}</h1></div>`;
const createResetButton = () => `<button data-role="reset">Reset</button>`;
const createUndoRedo = () => `
<div>
<button data-role="undo_redo" data-direction="-1">Undo</button>
<button data-role="undo_redo" data-direction="1">Redo</button>
</div>
`;
const paint = state =>
state.container.innerHTML =
createTable(state.grid) +
createMessage(state.message) +
createResetButton(state) +
createUndoRedo();
const init = state => state.container.addEventListener(
"click",
e=>{
const role = e.target.getAttribute("data-role");
if(role==="turn"){
const xy = e.target.getAttribute("data-position");
handleEvent(role,xy.split(",").map(Number));
}
if(role==="reset"){
handleEvent(role,{});
}
if(role==="undo_redo"){
const direction = e.target.getAttribute("data-direction");
handleEvent(role,Number(direction));
}
}
);
return [init,paint];
})();
const handleEvent = (()=>{
const createState = ([x,y])=>({
grid:Array.from(new Array(x),()=>Array.from(new Array(y),()=>"-")),
container:document.querySelector("#content"),
currentPlayer:"RED",
winner:false,
message:`It's RED's turn`
});
var state = createState([7,6]);
const isWin = (grid,position) => {
const [x,y] = position;
const player = grid[x][y];
if(player==="-"){//current location in grid is empty, return false
return false;
}
const countConnectedAllDirections = (directions,position,player) => {
const connectCount = (direction,position,player,count=1)=>{
const [x,y]=[position[0]+count*direction[0],position[1]+count*direction[1]];
if((grid[x] && grid[x][y])!==player){
return count;
}
return connectCount(direction,position,player,count+1);
};
return directions.map(
([back,forward])=>[connectCount(back,position,player),forward]
).map(
([countBack,forward])=>[countBack,connectCount(forward,position,player)]
).map(
([countBack,countForward])=>countBack+countForward-1
).reduce(
(highest,item)=>(item>highest)?item:highest,0
);
}
const directions = [[0,-1],[-1,-1],[-1,0],[-1,1]].map(([x,y])=>[[x,y],[x*-1,y*-1]]);
return countConnectedAllDirections(directions,position,player)>=4;
};
const getAvailableIndex = (grid,x)=>{
const getIndex = (arr,y) => {
if(arr[y]==="-"){
return y;
}
if(y<0){
return false;
}
return getIndex(arr,y-1);
}
return getIndex(grid[x],grid[x].length-1);
}
const play = (player,grid,[posX,posY])=>{
return grid.map((arr,x)=>arr.map(
(val,y)=>(x===posX && y===posY) ? player : val
));
}
const rotateGrid = grid =>
grid[0].map((i,y)=>grid.map((i,x)=>[y,x]))
.map((row)=>row.map(([y,x])=>[x,y,grid[x][y]]));
const paintRotate = state => paint({...state,grid:rotateGrid(state.grid)});
const canMove = grid => grid.reduce(
(result,ignore,index)=>result||(getAvailableIndex(grid,index)!==false),false
)
const handleEvent = ((states,statesIndex) => (eventType,data) =>{
const newState={...states[statesIndex]};
if(eventType==="turn"){
if(newState.winner){
return;
}
if(!canMove(newState.grid)){
newState.message=`It's a draw, press reset to play again.`;
paintRotate(newState);
return;
}
const availableY = getAvailableIndex(newState.grid,data[0]);
if(availableY===false){
newState.message=`Cannot play this move, still ${newState.currentPlayer}'s turn.`
if(states[statesIndex].message!==newState.message){
statesIndex=states.length;
states.push(newState);
paintRotate(newState);
}
return;
}
statesIndex=states.length;
const newGrid = play(newState.currentPlayer,newState.grid,[data[0],availableY]);
newState.grid=newGrid;
newState.winner=isWin(newState.grid,[data[0],availableY]);
if(newState.winner){
newState.message=`Winner is:${newState.currentPlayer}`;
states.push(newState)
paintRotate(newState);
return;
}
if(!canMove(newState.grid)){
newState.message=`It's a draw, press reset to play again.`;
states.push(newState);
paintRotate(newState);
return;
}
newState.currentPlayer=(newState.currentPlayer==="RED")?"GREEN":"RED";
newState.message=`It's ${newState.currentPlayer}'s turn`;
states.push(newState);
paintRotate(newState);
}
if(eventType==="reset"){
state = createState([newState.grid.length,newState.grid[0].length]);
statesIndex=states.length;
states.push(state);
paintRotate(state);
}
if(eventType==="undo_redo"){
const newIndex = statesIndex+data;
if(newIndex<0){
paintRotate({...states[statesIndex],message:"Cannot undo. "+states[statesIndex].message});
return;
}
if(newIndex>=states.length){
paintRotate({...states[statesIndex],message:"Cannot redo. "+states[statesIndex].message});
return;
}
statesIndex=newIndex;
paintRotate(states[statesIndex]);
}
})([state],0);
init(state);
paintRotate(state);
return handleEvent;
})();
td {
width:30px;
height:30px;
border:1px solid gray;
cursor:pointer;
}
<div id="content"></div>