как, если возможно, я могу сократить это?
if(moves[1] == moves[4] && moves[4] == moves[7]) { return 1;}
else if(moves[1] == moves[2] && moves[2] == moves[3]) { return 1;}
else if(moves[4] == moves[5] && moves[5] == moves[6]) { return 1;}
else if(moves[7] == moves[8] && moves[8] == moves[9]) { return 1;}
else if(moves[1] == moves[5] && moves[5] == moves[9]) { return 1;}
else if(moves[3] == moves[5] && moves[5] == moves[7]) { return 1;}
else if(moves[2] == moves[5] && moves[5] == moves[8]) { return 1;}
else if(moves[3] == moves[6] && moves[6] == moves[9]) { return 1;}
else if (moves[1] != '1' && moves[2] != '2' && moves[3] != '3' && moves[4] != '4' && moves[5] != '5' && moves[6] != '6' && moves[7] != '7' && moves[8] != '8' && moves[9] != '9') {
return 2;}
в значениях ходов хранится X или 0, который сравнивается, чтобы получить победителя в игре, и мне нужно максимально сократить его,
я не могу придумать другого способа сделать это из-за случайных комбинаций чисел
Приведенный выше код представляет собой функцию CheckWinner, которая передает данные, выбранные пользователем, с массивом позиций, которые были заполнены.
Код проверяет ход [позицию] по всем другим комбинациям выигрышного хода и возвращает 1, если выигрышный ход был обнаружен.
Последний бит кода проверяет все пробелы в сетке и, если не осталось пробелов, возвращает 2, чтобы вызвать ничью.
Надеюсь это поможет
Как насчет чего-то вроде этого:
#include <stdio.h>
int winners[8][3] = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{1, 4, 7},
{2, 5, 8},
{7, 8, 9},
{1, 5, 9},
{3, 5, 7}};
int moves[10] = { 0,
1, 2, 0,
0, 2, 0,
0, 2, 1};
int main()
{
int i;
for (i=0;i<8;++i)
{
if (moves[winners[i][0]] == moves[winners[i][1]] &&
moves[winners[i][1]] == moves[winners[i][2]])
printf("Player %d wins!\n",moves[winners[i][0]]);
}
return 0;
}
Массив победителей описывает различные выигрышные комбинации и тестирует петли каждой из них.
Не все числа случайны … Для строк формула N*3+1, N*3+2, N*3+3
для столбцов N+1, N+4, N+7
и т.д … где 0 <= N <= 2
, Много других способов представить это. Вы можете создавать отдельные функции для проверки строк, столбцов и диагоналей.
Просто проверьте строку, столбец и, возможно, диагонали для последней сыгранной игры. Вам не нужно проверять всю сетку.
Также используйте двумерный массив, так как вы храните сетка. Затем циклически перебирайте строки, ища совпадение, и перебирайте столбцы, ища совпадение
template <typename T> bool equal(T a, T b, T c) { return (a==b) && (b==c); }
int foo(char (&moves)[10])
{
auto eqset = [&](int i1, int i2, int i3) { return equal(moves[i1], moves[i2], moves[i3]); };
if (eqset(1,4,7) || eqset(1,2,3) || eqset(4,5,6) || eqset(7,8,9) || eqset(1,5,9) || eqset(3,5,7) || eqset(2,5,8) || eqset(3,6,9))
return 1;
else if (moves[1] != '1' && moves[2] != '2' && moves[3] != '3' && moves[4] != '4' && moves[5] != '5' && moves[6] != '6' && moves[7] != '7' && moves[8] != '8' && moves[9] != '9') {
return 2;
}
}
Оставаться довольно близко к буквально опубликованному коду. Обратите внимание, что не все пути кода возвращают значение, поэтому я остановился здесь.
В противном случае вы могли бы продолжить что-то вроде:
for (int i = 1; i<10; i++)
if (moves[i] == ('0'+i))
return 0; // ???
return 2;
Я не уверен, что это поможет, но я попробую:
то, что я сейчас вижу в вашем коде, это то, что большинство ваших условных выражений возвращают 1,
только в одном случае вы возвращаете 2. Поэтому я бы просто написал условие if для возврата 2,
И в все остальные случаи вернуть 1, не так ли?
например
if (moves[1] != '1' && moves[2] != '2' && moves[3] != '3' && moves[4] != '4' && moves[5] != '5' && moves[6] != '6' && moves[7] != '7' && moves[8] != '8' && moves[9] != '9') {
return 2;}
else
{
// return 1 probably
}
хм … нет, я возвращаю свои слова в коде выше, все остальные случаи возвращают 1, в то время как в вашем случае могут быть ситуации, когда вы не хотите, чтобы 1 возвращали …
Это делает проверку на победу … Вы могли бы сказать, что это «короче».
// Check rows and columns
for( int i = 0; i < 3; i++ ) {
char *row = &moves[3*i+1];
char *col = &moves[i+1];
if( row[0] == row[1] && row[0] == row[2] ) return 1;
if( col[0] == col[3] && col[0] == col[6] ) return 1;
}
// Check diagonals
if( moves[1] == moves[5] && moves[1] == moves[9] ) return 1;
if( moves[3] == moves[5] && moves[3] == moves[7] ) return 1;
Есть много других способов сделать это. Один из подходов — просто сохранить счетчик для каждой строки, столбца и диагонали. Если играется крест, вы добавляете 1 к соответствующим счетчикам. Если ничто не сыграно, вы вычитаете 1 из соответствующих счетчиков. Если какой-либо счетчик достигает 3 или -3, игра выиграна. Это занимает очень небольшое количество операций для каждой игры. Нет необходимости проверять всю доску.
Вы можете просто сократить свой код, используя макрос:
#define comp(i,j,k) (moves[i]==moves[j] && moves[j]==moves[k])
return comp(1,2,3) || comp(4,5,6) || comp(7,8,9)
|| comp(1,5,9) || comp(3,5,7) || comp(2,5,8);
В противном случае вы можете повернуть доску:
#define comp(i,j,k) (moves[i]==moves[j] && moves[j]==moves[k])
int rot[6][2] = { {1, 3}, {7, 9}, {9, 1}, {2, 6}, {4, 8}, {2, 8} };
for (int x = 0; x < 4; x++) {
if (comp(1,2,3) || comp(4,5,6) || comp(1,5,9)))
return 1;
for (int i = 0; i < 6; i++)
std::swap(moves[rot[i][0]], moves[rot[i][1]]);
}
return 0;
Вот полный код C ++ с пояснениями (это может быть простой C, а не C ++, но мне нравится std::swap
). Доска содержит бессмысленные числа, чтобы вы могли видеть вращение:
#include <iostream>
void print_tic(int moves[]) {
for (int i = 1; i < 10; i += 3)
std::cout << moves[i] << moves[i + 1] << moves[i + 2] << std::endl;
std::cout << std::endl;
}
void rotate(int moves[]) {
static const int rot[6][2] = {{1, 3}, {7, 9}, {9, 1}, {2, 6}, {4, 8}, {2, 8} };
for (int i = 0; i < 6; i++)
std::swap(moves[rot[i][0]], moves[rot[i][1]]);
}
int comp(int moves[], int i, int j, int k) {
return moves[i]==moves[j] && moves[j]==moves[k];
}
int main() {
int moves[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //meaningless.
print_tic(moves);
for (int x = 0; x < 4; x++) {
rotate(moves);
print_tic(moves);
if (comp(moves, 1,2,3) // first row
|| comp(moves, 4,5,6) // second row - forget that earlier
|| comp(moves, 1,5,9)) // main diagon
return 1;
}
return 0;
}
с распечатками вы можете увидеть повороты:
123
456
789
741
852
963
987
654
321
369
258
147
123
456
789
Вы можете вращать только один раз, по прошествии еще одного comp()
за третью строчку.