Альтернатива if-else - PullRequest
2 голосов
/ 19 марта 2009

У меня есть программа, которую я пишу, которая работает по принципу заполнения двумерного массива для проверки условия выигрыша, его пересечений и пересечений, поэтому двумерный массив заполняется нажатием кнопки, 1 для круга, 2 для креста, тогда checkWin () будет работать по этому принципу, а не по фактическому коду ...

if (myArray[0][0] == 1 && myArray[0][1] == 1 && myArray[0][2] == 1){
    setBoolWinVal = true;
} else {
    if(myArray[0][0] == 2 && myArray[0][1] == 2 && myArray[0][2] == 2){
    setBoolWinVal = true;
}

Вы сразу видите, что для каждого условия выигрыша это будет грязно, есть ли способ переписать этот чек на выигрыш, чтобы немного его сократить?

Ответы [ 12 ]

7 голосов
/ 19 марта 2009

Это похоже на домашнее задание, поэтому я не отдам его полностью. Но обратите внимание на несколько вещей:

  • Вы выигрываете, когда у вас есть три одинаковых предмета подряд, в столбце или по диагонали.

  • Дело не в том, что вам нужно проверять, есть ли три нолики или три крестика в линии, а в том, что в строке три одинаковых вещи .

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

3 голосов
/ 19 марта 2009

Вот (непроверенный) код. Это конечно не качество продукции :)

Обратите внимание на некоторые из оптимизаций из других ответов:

  1. Использование for-loop
  2. Мы проверяем равные значения игрока, а не конкретные значения игрока
  3. Диагональный выигрыш должен проходить через ячейку [1] [1]

.

int find_winner(int[][] arr) {

    // check rows
    for (int i = 0; i < 3; ++i) {
        int player = arr[i][0];
        if (player < 1) continue; // nb: prior version didn't check for empty cells
        if (arr[i][1] == player && arr[i][2] == player) return player;
    }

    // check cols
    for (int i = 0; i < 3; ++i) {
        int player = arr[0][i];
        if (player < 1) continue;
        if (arr[1][i] == player && arr[2][i] == player) return player;
    }

    // check diagonals
    int player = arr[1][1];
    if (player < 1) return -1;

    if ((arr[0][0] == player && arr[2][2] == player) ||
        (arr[2][0] == player && arr[0][2] == player)) return player;

    // no winner found
    return -1;
}
2 голосов
/ 19 марта 2009

Очевидный способ - перебрать 3 элемента в строке, столбце или диагонали и проверить, совпадают ли они.

Другой способ - использовать более компактное представление - например, int, где 9 ячеек представлены 2-мя битами или двумя шортами, по одному для каждого игрока. Затем используйте таблицу соответствия или побитовые операции, чтобы отобразить состояние для выигрыша и проигрыша.

Если один бит представляет ячейку, и у вас есть один бит заполнения, плитки каждого игрока представляют собой 3 шестнадцатеричные цифры 0-7.

Диагональная линия:

cells & 0x421 == 0x421
cells & 0x124 == 0x124

вертикальная линия:

cells & (cells>>4) & (cells>>8) != 0

горизонтальная линия

cells & (cells>>1) & (cells>>2) != 0

Подобные методы используются с использованием 64-битных шаблонов для представления возможных ходов в шахматных играх.

1 голос
/ 19 марта 2009

Две забавные идеи для вас: (Я полагаю, лежащий в основе 1D массив, потому что это облегчает жизнь.)

Первый: Кодировать позиции для проверки. Например, если у вас есть одномерный массив, описывающий ваше поле:

diag[] = { { 0, 1, 2}, {3, 4, 5}, {6, 7, 8},
           { 0, 3, 6}, {1, 4, 7}, {2, 5, 8},
           { 0, 4, 8}, {6, 4, 2}};

затем выполните цикл diag: для каждого его элемента протестируйте три соответствующих поля (используйте diag[i] в качестве индекса вашего массива полей).

Секунда: Используйте битовое поле для представления вашего поля. Как java.util.BitSet. Затем закодируйте решения в битовые поля, такие как {1, 1, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0} и так далее. Затем вы можете проверить (зациклить), если (field & solution[i] == solution[i]). Для второго игрока просто используйте !field в операторе if.

Весело, не правда ли? p.s .: вы должны сделать из этого рабочий Java-код!

0 голосов
/ 19 марта 2009

Простое, но элегантное решение - вы назначаете номера с 1 по 9 на вашу доску следующим образом:

8 1 6
3 5 7
4 9 2

Этот квадрат обладает уникальной характеристикой: каждая строка, столбец и диагональ суммы до 15, и невозможно получить сумму 15 из трех ячеек , если они разделяют строку, столбец или диагональ.

Для каждого игрока у вас есть два логических массива:

boolean squarePairs[PAIRSMAXSUM+1];
boolean chosenSquares[NUMSQUARES+1];

, где PAIRSMAXSUM = 9 + 8 и NUMSQUARES = 9

Затем вы можете легко проверить выигрышный ход, вызвав эту функцию:

boolean hasWon(int squareIndex) {
    return squarePairs[WINNINGSUM - squareIndex];
}

где WINNINGSUM равно 15. И если эта функция возвращает false, вы обновите логические массивы, вызвав эту функцию:

void update(int squareIndex) {
    for (int i = 1; i <= NUMSQUARES; i++) {
        if (chosenSquares[i]) {     {
            squarePairs[i + squareIndex] = true;
        }
    }
    chosenSquares[squareIndex] = true;
}


Все просто!

0 голосов
/ 19 марта 2009

Вы также можете решить это итеративно:

  1. Создание массива для каждого типа маркера для каждого столбца, строки и диагонали. Инициализировать на ноль.
  2. Для каждой записи в сетке, если она имеет маркер, увеличивайте соответствующий столбец, строку и диагональные записи для этого маркера.
  3. Если какая-либо из этих записей равна размеру доски, этот маркер выигрывает.
0 голосов
/ 19 марта 2009

Для n X n матрицы ...

//Check all horizontal rows
for(i=0; i<n && !setBoolWinVal; i++) //row
{
    setBoolWinVal = true;
    for(j=0; j<n-1; j++)
    {
        if( myArray[i][j] != myArray[i][j+1] ) //column
        {
            setBoolWinVal = false;
            break;
        }
    }

    if(setBoolWinVal) declareWinner(myArray[i][0]);
}

//Check all vertical columns
if(!setBoolWinVal)
{
    for(i=0; i<n && !setBoolWinVal; i++) //column
    {
        setBoolWinVal = true;
        for(j=0; j<n-1; j++) //row
        {
            if( myArray[j][i] != myArray[j+1][i] ) 
            {
                setBoolWinVal = false;
                break;
            }
        }
    }

    if(setBoolWinVal) declareWinner(myArray[0][i]);
}


//Check forward diagonal
if(!setBoolWinVal)
{
    setBoolWinVal = true;
    for(i=0; i<n-1; i++)
    {
        if( myArray[i][i] != myArray[i+1][i+1])
        {
            setBoolWinVal = false;
            break;
        }
    }

    if(setBoolWinVal) declareWinner(myArray[0][0]);
}

//Check reverse diagonal
if(!setBoolWinVal)
{
    setBoolWinVal = true;
    for(i=0, j=n-1; i<n-1 && j>0; i++, j--)
    {
        if( myArray[i][j] != myArray[i+1][j-1])
        {
            setBoolWinVal = false;
            break;
        }
    }

    if(setBoolWinVal) declareWinner(myArray[0][n-1]);
}
0 голосов
/ 19 марта 2009
  1. представляет доску как int в 0..19683 (с 3 по 9)
  2. предварительно сгенерируйте выигрышные доски и определите, кто является победителем на каждой доске, возможно, вручную
  3. во время выполнения ищите текущую доску на предварительно рассчитанной карте
0 голосов
/ 19 марта 2009

это действительно звучит как домашнее задание, но я помогу с простым вопросом - пройтись по строкам и столбцам, проверить, все ли они заполнены, диагональ немного сложнее, и я оставлю это на ваше усмотрение. Опять же, я считаю, что лучшим вариантом будет вложенный цикл for:

java.util.Arrays;

public yourClass{

public void findAnswer{

int initialVal = 0;

int copy = 0;

int column = 0;

boolean columnVal = true;

boolean rowVal = false;

for (int j = 0; j< myArray.length; j++){ //presuming myArray and myArray[] are same length

boolean firstRun = true;

    for (int i = 0; i <myArray.length; i++){

        initialVal = myArray[i][column];
        if (firstRun == true){
            copy = intialVal; //makes a copy for the first time, to compare
            firstRun = false;
        }
        if (intialVal != copy){
            columnVal = false; //realises this column isnt a full column i.e. 3 1's or 2's in column
            return;
        }else
            columnVal = true;

        }//end nested for loop

    rowVal = findRow(j); 
    if(rowVal = true)
    return;
}

public boolean findRow(int row){

    int[] tempRow1, tempRow2;
    Arrays.fill(tempRow1, 1); 
    Arrays.fill(tempRow2, 2); //fills temp arrays for comparison
    boolean answer = false;
    if (Arrays.equals(myArray[], tempRow1) || Arrays.equals(myArray[], tempRow2) //this tests either, || being logical OR
        answer = true;
    return answer;
}
}

n.b. этот код не проверен, и он был быстро закодирован, поэтому выглядит не очень хорошо, его можно улучшить, и я также не реализовал диагонали. постскриптум если это домашнее задание, то, вероятно, лучше всего поискать что-нибудь в Интернете и попытаться решить это самостоятельно, а не искать помощи, попросив других сделать это за вас.

0 голосов
/ 19 марта 2009

Итак, если вы думаете об этом, вы проверяете условия, где:

www   xxx   xxx  wxx
xxx   www   xxx  xwx
xxx   xxx   www  xxw

и т.д.

Где w - те, кто проверяет выигрыш, а x - игнорируют.

(0,0), (0,1), (0,2) - местоположения буквы "w" в первом правильном решении. 1,0, 1,1 и 1,2 - вторые и т. Д.

Мне кажется, это должны быть данные, а не код. Хитрость в том, как эффективно вводить и хранить данные.

Обратите внимание, что эти данные начинают выглядеть как индексы вашего массива.

Допустим, у вас был массив «Решений», в котором было 8 пар х, у (каждая из которых указывала на выигрышную комбинацию решений)

Тогда все, что вам нужно сделать, - это перебрать эту коллекцию, извлечь три пары x, y и проверить их. так что это будет похоже на то, что у вас есть, но используйте переменные там, где у вас есть числа.

if(myArray[x0][y0] == 2 && myArray[x1][y1] == 2 && myArray[x2][y2] == 2){
    win();

При итерации по ней индексные переменные будут заменены следующей строкой ваших данных.

Поскольку вы не хотите сообщать о проигрыше после победы, вам придется немного поиграть с логикой, чтобы убедиться, что ваш цикл останавливается, но это, вероятно, уже слишком много для решения проблемы стиля домашней работы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...