Правильный способ использования! = В цикле while? … Или ..?

Я всего лишь новичок в 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;
}

0

Решение

Проблема здесь в вашем тестовом состоянии. Ваш цикл повторяется, если вы вводите 2, 3, 4, 6, 7 или 8. Как только вы вводите 1, 5 или 9, цикл завершается. Если вы введете 1, 5 или 9, то одно из диагональных значений будет установлено на 'X', while циклы, пока условие выполняется. Как только условие оценивается как ложное, оно завершается. Когда вы вводите 1, 5 или 9, вы заставляете условие быть ложным.

Представьте на секунду, что 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

Если вы логически И эти вместе (как вы с &&), это оценивает 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' в одной из этих позиций пользователь не может иметь 3 подряд. Это всего лишь приложение Законы де Моргана к предыдущему логическому утверждению.
3

Другие решения

Важной частью обучения программированию является обучение тому, чтобы избегать повторения подобных вещей в исходном коде. Вам необходимо абстрагировать подобное поведение, чтобы они могли использовать один фрагмент кода. Таким образом, компьютер выполняет всю эту работу, но при написании исходного кода вы не выполняете всю эту работу.

Ваша попытка создать гигантское логическое выражение состояния игры является крайним примером того, как не программировать. Это распространенная ошибка новичка (и далеко не единственный пример этой ошибки новичка в вашем коде). Исправление этого гигантского логического выражения возможно, но это будет ужасно контрпродуктивно на вашем пути обучения программированию. Вместо этого вы должны взять это в качестве примера, чтобы научиться комбинировать и абстрагировать работу:

Сначала разберитесь с игровыми концепциями: состояние игры — это одно из следующих: wonX, wonY, draw, inProgress. Вы можете определить перечисление для этих возможностей. Каждая из восьми линий на доске имеет четыре одинаковых возможных состояния, в которых игровое состояние имеет значение wonX или wonY, если какая-либо строка имеет это состояние, а игровое состояние находится в состоянии Ingress, ни одна строка не является wonX или wonY, а некоторая строка является inProgress.

Поскольку отрисовка объединяется от отдельной линии до уровня платы противоположным образом, как выигрывают или выигрывают, операция объединения будет сложной на высоком уровне и проще в коде, который также определяет состояние линии.

Поэтому я предлагаю написать функцию, которая принимает три значения одной строки в качестве входных данных, а также принимает накопитель состояния игры в качестве входных данных и возвращает обновленное состояние игры. В каждом раунде вы начинаете вычислять игровое состояние как ничью, а затем вызываете функцию для каждой из 8 линий, чтобы обновить ее. Если линия является победой для X или Y, то состояние безоговорочно изменится на это. Если линия inProgress, состояние изменится на это только в том случае, если состояние было нарисовано. Если линия ничья, это не меняет состояние (одна линия в состоянии ничьи ничего не говорит о состоянии игры).

Хороший дизайн будет дополнительно абстрагировать и объединять еще несколько аспектов вашего кода, но одна из проблем, которая связана с вашей неспособностью абстрагироваться и комбинироваться, состоит в том, что, как я указал, шаг, который просматривает одну строку и вычисляет ее влияние на состояние вся доска.

В общем, вы найдете свой самый мощный инструмент для абстрагирования и объединения работ — это переместить этот кусок работы в функцию (как я описал выше). Попытка сделать слишком много, не разделить на отдельные функции, является большой ошибкой новичка.

1

По вопросам рекламы [email protected]