在过去的四天里,我花了四天时间研究承诺、协程、纤维、延续等。
我仍然无法理解如何解决我的多人回合制纸牌游戏动作,其中起始玩家实际上是最多五个游戏"控制器",无论是 AI 玩家还是人类玩家。
下面的代码有效,但有一个问题:-
它无法检测到人类OPPO的卡牌移动,因此在没有它们的情况下继续玩,这当然会弄得一团糟。
任何人都可以建议更改我的整体概念或使用承诺或任何其他"同步"结构之一的方法吗?
以下是我的代码的四个关键领域:
function oppoPlays () {
// can only go through here if game starter
if (joiner!="") {return;}
for (pp=1; pp<numberofplayers; pp++) {
if (oppoType[pp] == "AI") {
// an AI player moves
.
.
} else {
// non-AI player
var yourTurnmsg="It's "+playerNames[pp]+"'s turn";
// tell human player that it's their turn
$("#text_message").val(yourTurnmsg).trigger(jQuery.Event('keypress', { keyCode: 13, which: 13 }));
// how to detect human oppo's card moved?
}
}
}
// chat functionality
$("#text_message").on("keypress", function(e) {
if (e.keyCode == 13){
payload = new Object();
payload.action = 'chat_text';
payload.chat_text = tmsg; // It's michael29's turn
payload.user_id = playerNames[pp];
payload.game_no = game_no;
socket.send(JSON.stringify(payload));
}
});
// socket gets oppo's response
function checkJson(res, sttr_id, game_no) {
if(res.action=="game_move"){
// find player
var pp=playerNames.indexOf(res.user_id);
cpos=res.cardno;
playCard_oppo(pp, cpos);
}
}
// turn an oppo's card face up and update scores
function playCard_oppo(pp, cardno) {
// and move it to the stack
topoc= parseInt($("#oppo_card" + cardno).css('top'));
leftoc=parseInt($("#oppo_card" + cardno).css('left'));
$("#oppo_card" + cardno).css({ top: topoc, left: leftoc, opacity: "50%" });
.
.
if (joiner=="") {
// tell oppoPlays fn that the card has moved
}
}
该游戏在概念上类似于uno,但具有得分组件
(旨在帮助孩子进行基本算术(。
考虑让一个全局的棋盘状态,玩家/AI 移动对其进行修改。然后,当AI对手采取行动时,它会参考当前的董事会状态并决定移动。
如果您的板状态仅由页面上的元素表示,则需要一种方法来扫描它并计算板状态的有用内存中表示形式。如果没有实现的详细信息,就很难更具体。
也许开始考虑游戏周期,像这样:
- (主机(广播游戏状态。
- (主机(等待所有客户端确认已收到广播。
- (客户端(呈现游戏状态。 (
- 主机(收到确认,然后通知下一个客户端(以及它的玩家(轮到他/她/它了。
- (主持人(等待玩家的举动
- (客户端(解锁允许玩家移动的UI。
- (玩家(移动。
- (客户端( 发送移动命令并重新锁定 UI。
- (主机( 接收移动命令并相应地修改游戏状态。
然后回到 1。
此外,将AI玩家视为人类玩家的一个特例。如果你能为人类做对,那么(重新(引入人工智能应该相当简单。
解决方案围绕两件事:-
-
将AI玩家代码与人类玩家代码分开;
-
添加和删除在检测到人类移动后触发的窗口事件。
精简代码现在如下所示:-
// if this is game starter give each player a turn
if (joiner == "") {
// there's always at least one
pp = 1;
if (oppoType[pp] == "AI") { AIplays(); } else { humanPlays(); }
}
function humanPlays () {
// tell human player that it's their turn
var yourTurnmsg="It's "+playerNames[pp]+"'s turn"
$("#text_message").val(yourTurnmsg).trigger(jQuery.Event('keypress', { keyCode: 13, which: 13 }));
//window.addEventListener("humanPlayed", function(evnt) {
$(window).on("humanPlayed", function(evnt) {
endOfTurn();
});
}
function endOfTurn () {
if (!(winner)) {
if (pp++ != numberofplayers) {
if (oppoType[pp] == "AI") {
setTimeout(function (){ $("#clickForNextPlayer").show(); }, 1000);
} else {
$("#clickForNextPlayer").trigger('click');
}
}
}
}
// click for next player
$("#clickForNextPlayer").on('click', function() {
$("#clickForNextPlayer").hide();
$(window).off("humanPlayed");
if (pp == numberofplayers) {
// uncover outStack for game starter to play
$("#outStackcover").hide();
return;
}
if (oppoType[pp] == "AI") { AIplays(); } else { humanPlays(); }
});
function AIplays () {
AIcardno = chooseCard(pp, diffLevel);
.
.
if ($("#chatWindow").is(":visible")) {
payload = new Object();
payload.action="game_move";
payload.game_no=gamestarted;
payload.user_id=playerNames[pp];
payload.cardno=AIcardno;
socket.send(JSON.stringify(payload));
}
$("#oppo_card" + cc).css('background-image', "url(JerseyTeam" + playerNumbers[(pp == numberofplayers ? 1 : pp)] + ".gif)");
outStackturn();
endOfTurn();
}