4

ちょっとした問題があります。

コンピューター サイエンスのクラスの最後の課題は、三目並べのゲームを JavaScript で作成することです。このゲームは、テーブル内のセルをクリックし、function() を使用して img ソース (クリックされるまで空白の画像) を X または O に切り替えることで機能します。 .

ゲームは、明らかに、2 人のプレイヤーによってプレイされます。私が必要とする最後のことは、プレイヤーがいつ勝ったかを検出し、これが発生したときにスクリプトを強制終了する (関数) を取得することです。私はこれを理解することはできません。if ステートメントが含まれていることはわかっており、いくつかの異なるコードを試しましたが、コーディングしたものはすべてゲームを壊してしまいます。

この質問は以前に尋ねられたことがわかりました。右側の「同様の質問」ボックスにあるいくつかのリンクをクリックしてみましたが、それらはすべて、私が何も学んでいない言語 (C# など) で書かれています。 .

これが私のスクリプトです:

<script type="text/javascript" charset="ISO-8859-1">
function placeMove(value)
{
    if (document.getElementById(value).src.indexOf("FC")!=-1) //"FC" because of the FC contained in the file name. I intended for it to stand for "free cell", for easy indentification.
    {
        var turn = document.getElementById("playerturn").innerHTML;
        if (turn == "X")
        {
            document.getElementById(value).src="../Images/TicTacToeX.jpg";
            document.getElementById("playerturn").innerHTML="O";
        }
        if (turn == "O")
        {
            document.getElementById(value).src="../Images/TicTacToeO.jpg";
            document.getElementById("playerturn").innerHTML="X";
        }
    }
    else
    {
        window.alert("Tile is in use. Please select another tile.");
    }
}
function detectWin()
{

}
</script>

これは、ゲームが行われるテーブルです。

<table class="gametable" id="gametable" border="1">
<tr>
    <td><img onclick="placeMove('r1c1')" id="r1c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r1c2')" id="r1c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r1c3')" id="r1c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr> 
<tr>
    <td><img onclick="placeMove('r2c1')" id="r2c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r2c2')" id="r2c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r2c3')" id="r2c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
<tr>
    <td><img onclick="placeMove('r3c1')" id="r3c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r3c2')" id="r3c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r3c3')" id="r3c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
</table>

課題の期限は明日で、必要なのはこの最後の小さなコードだけです。

どんな助けでも大歓迎です。これが今学期最後の課題です。

ありがとう、

カイル

編集:いくつかの提案の後、ここに私が試してきたことがあります。このコードを入力すると、ゲームをプレイできなくなります。セミコロンが足りないだけの場合は、ご容赦ください。各セルの img ソースを変数に設定し、それらの変数が一致するかどうかを確認します。

セル/X または O 画像ごとに 1 つずつ、作成した 9 つの変数があります。

var pic1 = document.getElementById("r1c1").src;
var pic2 = document.getElementById("r1c2").src;
var pic3 = document.getElementById("r1c3").src;
var pic4 = document.getElementById("r2c1").src;
var pic5 = document.getElementById("r2c2").src;
var pic6 = document.getElementById("r2c3").src;
var pic7 = document.getElementById("r3c1").src;
var pic8 = document.getElementById("r3c2").src;
var pic9 = document.getElementById("r3c3").src;

これは、最初のスクリプトの最後にあります。

function detectWin()
{
if (var pic1 == var pic2 && var pic3)
{
window.alert("Game won. Please reset the game.");
}
}

これは明らかに最初の行の勝利のみを検出します。これを機能させることができれば、残りのコードがどうあるべきかがわかります。ただし、スクリプトを強制終了する方法はまだわかりません。

不要な発言や文法上の誤りを削除するために編集されました。

4

7 に答える 7

5

誰がゲームに勝つかを確認する私のバージョンを確認できる最初のコードから書きます。私のゲームのバージョンがあなたとは異なる場合は、反対票を投じないでください。アルゴリズムの知識がなくてもコードを記述できる方法を示したいだけです。

必要なのはモチベーションだけです。次はそんなに早くあきらめないで。

jsフィドル

誰が勝つかを確認するための私のバージョン:

var checkResult = function(){
    $("table tr").each(function(i, val){
        $(this).find('td').each(function(j, val2){
            arr[i][j] = parseInt($(this).attr("data-points"));
        });
    });

    for(var i = 0; i<3;i++){
        var rowSum = 0;
        for(var j = 0; j<3;j++){
            rowSum += arr[i][j];
        }
        if(rowSum === 3)
            alert("Circle WIN!");
        else if(rowSum === -3)
            alert("Cross WIN!");
    }

    for(var i = 0; i<3;i++){
        var colSum = 0;
        for(var j = 0; j<3;j++){
            colSum += arr[j][i];
        }
        if(colSum === 3)
            alert("Circle WIN!");
        else if(colSum === -3)
            alert("Cross WIN!");
    }

    if(arr[0][0] + arr[1][1] + arr[2][2] === 3)
        alert("Circle WIN!");
    else if(arr[0][0] + arr[1][1] + arr[2][2] === -3)
        alert("Cross WIN!");

    if(arr[2][0] + arr[1][1] + arr[0][2] === 3)
        alert("Circle WIN!");
    else if(arr[2][0] + arr[1][1] + arr[0][2] === -3)
        alert("Cross WIN!");
};
于 2013-05-15T19:07:12.350 に答える
1

Stack Overflow で同様の質問を検索したとおっしゃっていましたね。プログラミングが初めてで、別の言語で何かを読むのは簡単ではありませんが、基本的な考え方はそこにあります。これがすでに行われているリンクは次のとおりです: Algorithm for Determining Tic Tac Toe Game Over

そうは言っても、ゲームで勝つには基本的に 3 つの方法があり、vars で正しい方向に向かっています。

勝つための3つの方法は、

  1. 3試合連続
  2. 3マッチダウン
  3. 3 マッチ対角線。

簡単な部分は行と列です。単純に各行/列をループして、3 つの一致があるかどうかを確認し、一致した場合は勝者を宣言できます。

非効率的な疑似コードの例:

if pic1, pic2, and pic3 are the same
alert user X or O has won
end the game.

行 2 と行 3 について繰り返します。

if pic1, pic4, and pic7 are the same
alert user X or O has won
end the game.

列 2 と 3 について繰り返します。

対角線は、例の 2 次元配列を使用せずに、単純な方法でも実行できます。基本的に、斜めに勝つ可能性は 2 つだけです。

  1. var 1、5、9 一致
  2. var 3、5、7 が一致します。

それ以外は、引き分けでゲームを終了できます。リンクの例に示されているように、カウンターを使用することをお勧めします。

幸運を!-- わかりやすくするために編集 --

于 2013-05-15T17:33:09.183 に答える
1

これに対する答えを誠意を持ってお伝えすることはできませんが、この問題について 1 つの考え方を説明することはできます。それが最善の解決策であるとは決して言えませんが、少なくとも最初の一歩を踏み出すことはできます。

勝者を検出するには、次のいずれかが成立する必要があります。

  1. 任意の行の 3 つのセルはすべて同じです
  2. 任意の列の 3 つのセルはすべて同じです
  3. ボードを斜めに横切る 3 つのセルはすべて同じです。

幸いなことに、テーブル要素をループして、このチェックを簡単に行うことができます。

あなたが提供したif声明には欠陥があります。var変数を既に宣言した後は、変数の前に を付ける必要はありません。さらに、あなたの使い方&&は間違っています。これが行うことは、左のステートメント (この場合は ) が truevar pic1 == var pic2かどうかをチェックし、次に右のステートメント (単に ) も true かどうかをチェックすることですvar pic3true これは、Javascript のブール値の最適な解釈 (この場合はpic3 が定義されている限り)に自動的にキャストされるため、これ自体は適切なステートメントではありません。代わりに、次のようなものが必要になりますif(pic1 == pic2 && pic2 == pic3)、しかし、私はあなたがしていることである画像を比較する以外に何かを使用します. 各セルのクラスを、そこに移動するピースに応じて「X」または「O」に変更できます。これにより、もう少しエレガントになります。

.classNameクラス名は、次の呼び出しでアクセスできます。

<div id="foo" class="bar"></div>

<script>
    document.getElementById("foo").className; //returns "bar"
</script>

要素のクラスを変更する方法の詳細な説明を次に示します。

于 2013-05-15T17:41:36.230 に答える
1

ボードをどのように表示するかによって異なります。

私はTic-Tac-Toeゲームを ( Reactで) コーディングし、フラット配列を選択しました。これは、(ゲームの他の側面でも) 操作が簡単であると信じているためです。

すべての可能な勝利位置が事前に定義されている方法で勝利検出コードを作成しました。ゲーム ボードを表す配列は 2 つの文字列 (プレーヤーごとに 1 つ) の配列に変換されるため、各文字列にはこの特定のプレーヤーが選択したセルのインデックス。

/**
 * 
 * @param {Array} board - flat array representation of the board, 
 * from right to left, top to bottom, Ex.
 * [1,2,2,1,1,2,1,2,1] 
 */
function checkWin(board){
  // all possible winning combinations (of cells filled by the same player)
  const winMap = [123, 456, 789, 147, 258, 369, 357, 159]

  // convert the board to array represening the filled cells, per player.
  // each array item is a string of only the cells (indices) filled by a player
  const moves = board.reduce((players, v, i) => {
    if(v) players[v-1] += i+1
    return players
  }, ['', ''])

// console.log(JSON.stringify(moves))

  // find & return the winning combination
  const winningMove = winMap.find(comb =>
    moves.some(m => // there are only 2 sets of moves, one for each player
      // break down the current combination to array and check if every item exists
      // also in the current set of moves. quit on first match.
      comb.toString().split('').every(c => m.includes(c))
    )
  )

  return winningMove ?
    { // get the first number of the winning-move, 
      // substract 1 from it, and use as index to find which
      // player played that move from the board Array
      player: board[winningMove.toString()[0] - 1],
      move: winningMove
    } 
    : false
}


// sample tests:
[
  [1,1,1,2,2,2],       // player 1 wins, horizontal, row 1
  [1,2,2,1,,,1],       // player 1 wins, vertical, col 1
  [2,1,1,1,2,1,2,1,2], // player 2 wins, diagonal to right
  [1,1,2,1,2,1,2,1,2], // player 2 wins, diagonal to left
  [1,2,1,1,2,1,2,1,2]  // no win
].forEach(board => console.log(
  checkWin(board)
))

于 2020-10-28T10:05:01.260 に答える
0

さらにいくつかの最適化。

  1. 両方のプレイヤーのピースが少なくとも 1 つ含まれているため、ボード上のどの「ライン」が決して勝てないかを識別するメカニズムを追加します。これらは、その行の将来のチェックを防ぎ、速度を向上させるためにキャッシュされます。
  2. (ルールに従っている間)勝利を可能にするのに十分なピースがない場合、高価な勝利チェックを無視します。たとえば、プレーヤーが 3x3 ボードで最も早く勝つことができるのは、5 番目のマスをマークするときです。
于 2017-12-29T21:56:01.920 に答える