0

私は C++ の初心者で、TicTacToe ゲームを作成するためのコードを作成しているときに、勝利条件が満たされるまでゲームを続行するようにプッシュする while ステートメントに行き詰まりました。

 while(((table[0][0]!='X')&&(table[1][1]!='X')&&(table[2][2]!='X')))

これはあくまでも対角線上の条件です(条件を全部入れると目障りになりますが…)。問題は、条件が満たされていてもこれが機能しないことです (最後に cout を使用しているためだと思います)、 && を || で変更すると 状態動作!すべてに影響を与える != のせいではないかと思いました??

編集:最小限の例(浮動小数点を削除しました!):

#include <iostream>
using namespace std;
int main()
{
    int tailleX(3),tailleY(3); //The Size of the table.
    char table[tailleX][tailleY]; //TictacToe table.
    table[0][0]='N';
    table[0][1]='N';
    table[0][2]='N';
    table[1][0]='N';
    table[1][1]='N';          //Randomly filling the array to avoid an error
    table[1][2]='N';
    table[2][0]='N';
    table[2][1]='N';
    table[2][2]='N';
    int coorP1; //The Coordinate of the square (Exp: x=1 , y=2 will be 1.2)
    while(((table[0][0]!='X')&&(table[1][1]!='X')&&(table[2][2]!='X'))) //For the minimal example I made just the diagonal condition
    {
    cout<<"PLAYER1: Enter the coordination to score: (Exemple: 1, 2, 3..) "<<endl;
    cin>>coorP1;
    switch(coorP1) //Filling the square depending on the coordinates.//I used If because Switch does not work.
    {
        case 1:
    table[0][0]='X';
    break;
        case 2:
    table[0][1]='X';
    break;
        case 3:
    table[0][2]='X';
    break;
        case 4:
    table[1][0]='X';
    break;
        case 5:
    table[1][1]='X';
    break;
        case 6:
    table[1][2]='X';
    break;
        case 7:
    table[2][0]='X';
    break;
        case 8:
    table[2][1]='X';
    break;
        case 9:
    table[2][2]='X';
    break;
    }
    }
    cout<<"You won"<<endl;
    return 0;
}
4

2 に答える 2

3

ここでの問題は、テスト条件です。2、3、4、6、7、または 8 を入力すると、ループが繰り返されます。1、5、または 9 を入力するとすぐに、ループが終了します。1、5、または 9 を入力すると、対角値の 1 つが に設定され'X'ます。while条件が真の間ループします。条件が false と評価されるとすぐに終了します。1、5、または 9 を入力すると、条件が false になります。

ちょっと想像してみtable[0][0]てください。つまり、ボードは次のようになります。'X'table[1][1]'N'table[2][2]'N'

X | N | N
--+---+---
N | N | N
--+---+---
N | N | N

次に、テスト条件は次のとおりです。

table[0][0] != 'X' && table[1][1] != 'X' && table[2][2] != 'X'
^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^
false                 true                  true

これらを論理的に AND で結合すると ( の場合のように&&)、これは に評価されますfalse(これは理にかなっています:false AND trueに評価する必要がfalseあります; にのみtrue AND true評価する必要がありますtrue)。

それで、あなたのテスト条件はどうあるべきですか?

本当にやりたいことは、ユーザーが 3 つ続けて持っていない場合にのみループすることです。つまり、ユーザーが 3 つ続けて持っているかどうかを確認します。彼が3つ連続していない場合は、次に進みます。

その論理ステートメントを次のように構成できます。

// This checks if the user has 3 in a row
table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X'

// We want to check if the user does NOT have 3 in a row,
// so we can negate the above with !
!(table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X')

// With De Morgan's laws, we can simplify this to:
table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'

したがって、ループ条件は次のいずれかである必要があります (どちらも同等です。より意味のある方を選択してください)。

  • !(table[0][0] == 'X' && table[1][1] == 'X' && table[2][2] == 'X')
    これは、ユーザーが 3 つ続けて持っていないかどうかを確認します
  • table[0][0] != 'X' || table[1][1] != 'X' || table[2][2] != 'X'
    'X'これは、ユーザーが必要な位置のいずれかを 持っていないかどうかを確認します。論理的には、ユーザーが'X'これらの位置の 1 つに欠けている場合、ユーザーは 3 つ続けて持つことはできません。これは、前述の論理ステートメントにド モルガンの法則を適用したにすぎません。
于 2015-07-22T15:25:10.510 に答える
1

プログラミング学習の重要な部分は、ソース コードで同じようなことを何度も行うことを避けることを学ぶことです。コードの 1 つのチャンクを共有できるように、同様の動作を抽象化する必要があります。つまり、コンピューターがすべての作業を行いますが、ソース コードを記述するときは、そのすべての作業を行うわけではありません。

ゲームの状態の巨大なブール式を構築しようとする試みは、プログラミングしない方法の極端な例です。これはよくある初心者の間違いです (そして、あなたのコードにおける初心者の間違いの唯一の例ではありません)。その巨大なブール式を修正することは可能ですが、プログラミングを学習する過程で非常に逆効果になります。代わりに、それを例として、作業を組み合わせて抽象化する方法を学ぶ必要があります。

まず、ゲームの概念を理解します。ゲームの状態は、wonX、wonY、draw、inProgress のいずれかです。これらの可能性の列挙型を定義できます。ボードの 8 本の線のそれぞれに同じ 4 つの可能な状態があり、いずれかの線にその状態がある場合、ゲームの状態は winX または winY であり、ゲームの状態は inProgress であり、線は winX または winY ではなく、一部の線は inProgress です。

描画は、wonX または winY とは逆の方法で個々の rline からボード レベルまで結合するため、組み合わせ操作は高レベルではトリッキーであり、ライン状態も決定するコードではより簡単になります。

そこで、1 行の 3 つの値を入力として取り、ゲーム状態アキュムレータも入力として取り、更新されたゲーム状態を返す関数を作成することをお勧めします。各ラウンドで、ドローとしてゲーム ステートの計算を開始し、8 行ごとに関数を呼び出して更新します。ラインが X または Y の勝利である場合、状態は無条件にそれに変わります。行が inProgress の場合、状態が draw である場合にのみ状態がその状態に変わります。線が描画の場合、状態は変わりません (描画状態の 1 つの線はゲームの状態について何も言いません)。

優れた設計は、コードのさらにいくつかの側面を抽象化して結合しますが、抽象化と結合に失敗したことによる大きな問題は、1 行を見て、その状態への影響を計算するステップを示したとおりです。ボード全体。

一般に、作業を抽象化して結合するための最も強力なツールは、その作業のチャンクを関数に移動することです (上記で説明したように)。別々の機能に分割せずに多くのことをしようとするのは、初心者の大きな間違いです。

于 2015-07-22T16:02:55.697 に答える