Форум программистов, компьютерный форум CyberForum.ru

Упрощение логического выражения - C++

Восстановить пароль Регистрация
 
Limpaku12
0 / 0 / 0
Регистрация: 21.07.2013
Сообщений: 4
21.07.2013, 13:45     Упрощение логического выражения #1
Всем привет. Сейчас решаю задачу про шахматного коня по книжке Дейтелов. Там предлагается высчитать доступность каждой клетки и двигать коня туда, где доступность наименьшая. Чтобы ее рассчитать, надо, грубо говоря, из каждой клетки походить конём. Идея, как считать доступность уже есть, выглядит она примерно так (тут как минимум нет проверки границы массива):

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//board - двумерный массив, изображающий доску
//x и y - координаты текущей точки, counter - счетчик, показывающий ту самую доступность для этой клетки
//значение -1 означает, что конь уже прошел по клетке
//инициилизировал то, что важно для понимания моей логики, конкретное значение остальных переменных/массивов не важно
 
int shift = {-1, 1, -2, 2};
counter = 0;
 
for (int i = 0; i < 2; i++)
   for (int j = 2; j < 4; j++) {
      if (board [ x + shift [i] ] [ y + shift [j] ] != -1) counter++;
      if (board [ x + shift [j] ] [y + shift [i] ]  != -1) counter ++; 
   }
 
board [x] [y] = counter;
Но при этом мне нужно сделать эту самую проверку границы массива. Ничего изящнее этого придумать не смог:

C++
1
2
3
4
5
6
7
8
const int boardSize = 8;
 
if ( (x + shift [i] >= 0) && (x + shift [i] < boardSize) && 
     (x + shift [j] >= 0) && (x + shift [j] < boardSize) && 
     (y + shift [i] >= 0) && (y + shift [i] < boardSize) && 
     (y + shift [j] >= 0) && (y + shift [j] < boardSize) ) {
   //код, если это безумие прошло проверку
}
Это просто ужасно выглядит, хотя и, по идее, должно сработать. Нет ли способа как-то упростить эту проверку? Чтобы выглядело понятнее и компактнее хотя бы.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Мимино
 Аватар для Мимино
180 / 151 / 5
Регистрация: 22.05.2013
Сообщений: 435
Записей в блоге: 1
21.07.2013, 13:51     Упрощение логического выражения #2
У меня все это вышло вот так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <iostream>
#include <iomanip>
using namespace std;
 
const int hor = 8, ver = 8;
 
void boardPrint(int [][ver], int);
int minAcces(int, int, int [][ver], int [], int [], int [][ver]);
void downAcces(int, int, int [][ver], int [], int []);
 
int main()
{
    setlocale(LC_ALL, "Russian");
    int board[hor][ver] = {0};
    int horizontal[hor] = {2, 1, -1, -2, -2, -1, 1, 2};
    int vertical[ver] = {-1, -2, -2, -1, 1, 2, 2, 1};
    int currentRow, currentColumn, moveNumber;
    bool status = false;
    int accessibility[hor][ver] = {{2,3,4,4,4,4,3,2},
                                   {3,4,6,6,6,6,4,3},
                                   {4,6,8,8,8,8,6,4},
                                   {4,6,8,8,8,8,6,4},
                                   {4,6,8,8,8,8,6,4},
                                   {4,6,8,8,8,8,6,4},
                                   {3,4,6,6,6,6,4,3},
                                   {2,3,4,4,4,4,3,2}};
    
    while (status == false)
    {
        cout << "Введите текущие координаты коня через пробел ([строка],[столбец])(0-7): ";
        cin >> currentRow >> currentColumn;
        if (currentRow < 8 && currentRow >=0 && currentColumn < 8 && currentColumn >=0)
            status = true;
        else
            cout << "Таких координат не существует. Попробуейте снова." << endl;
    }
 
    for (int i = 1; i <= 64; i++)
    {
        board[currentRow][currentColumn] = i;
        
        downAcces(currentRow, currentColumn, accessibility, horizontal, vertical);
        moveNumber = minAcces(currentRow, currentColumn, board, horizontal, vertical, accessibility);
 
        if (moveNumber != 9)
        {
            currentRow += vertical[moveNumber];
            currentColumn += horizontal[moveNumber];
        }
        
 
        else
        {
            cout << "Сделано ходов: " << i << endl;
            break;
        }
    }
    
    cout << endl;
    boardPrint(board, hor);
    system("pause");
    return 0;
}
 
 
 
void boardPrint(int b[][ver], int horiz)
{
    for (int i = 0; i < horiz; i++)
    {
        for (int j = 0; j < horiz; j++)
            cout << setw(4) << b[i][j];
        cout << endl << endl;
    }
}
 
 
int minAcces(int row, int column, int b[][ver], int hori[], int vert[], int accessibility[][ver])
{
    
    int minAcc = 9, moveNumber = 9;
 
    for (int j = 0; j < hor; j++)
        {
            if (row + vert[j] < 8 && row + vert[j] >=0 
                && column + hori[j] < 8 && column + hori[j] >=0 
                && b[row + vert[j]][column + hori[j]] == 0)
            {
                if (minAcc >= accessibility[row + vert[j]][column + hori[j]])
                {
                    minAcc = accessibility[row + vert[j]][column + hori[j]];
                    moveNumber = j;
                }
            }
        }
    return moveNumber;
}
 
 
void downAcces(int row, int column, int acces[][ver], int hori[], int vert[])
{
    for (int j = 0; j < hor; j++)
        {
            if (row + vert[j] < 8 && row + vert[j] >=0 
                && column + hori[j] < 8 && column + hori[j] >=0)
                acces[row + vert[j]][column + hori[j]]--;
            
        }
}
Limpaku12
0 / 0 / 0
Регистрация: 21.07.2013
Сообщений: 4
21.07.2013, 13:56  [ТС]     Упрощение логического выражения #3
Мимино,
Спасибо большое, но у меня уже есть подобное решение, сейчас я хочу максимально упростить код, чтобы буквально все просчитывалось компьютером. Вот и сижу, думаю, усложняя себе жизнь
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
21.07.2013, 14:05     Упрощение логического выражения #4
выносите код в функцию, дайте ей говорящее имя и тогда вызывающий код будет более лаконичным:
C++
1
2
3
4
5
const int boardSize = 8;
if (IsBlaBlaBla(x, y, shift, i, j, boardSize)
{
};
}
если захочется детали IsBlaBlaBla, то пожалуйста. там только и будет это толстое условие,
которое тоже на говорящие функции кстати можно разбить.
Мимино
 Аватар для Мимино
180 / 151 / 5
Регистрация: 22.05.2013
Сообщений: 435
Записей в блоге: 1
21.07.2013, 14:11     Упрощение логического выражения #5
Цитата Сообщение от Limpaku12 Посмотреть сообщение
чтобы буквально все просчитывалось компьютером.
Так оно и так просчитывается компьютером. Человек только координаты начала вводит, чтобы проверить в разных ситуациях.
Касательно темы, я не сильно понимаю, зачем Вам вот это все для проверки выхода за пределы доски
C++
1
2
3
4
5
6
if ( (x + shift [i] >= 0) && (x + shift [i] < boardSize) && 
     (x + shift [j] >= 0) && (x + shift [j] < boardSize) && 
     (y + shift [i] >= 0) && (y + shift [i] < boardSize) && 
     (y + shift [j] >= 0) && (y + shift [j] < boardSize) ) {
   //код, если это безумие прошло проверку
}
У меня эта проверка занимает всего 4 условия, у Вас - 8.
C++
1
2
if (row + vert[j] < 8 && row + vert[j] >=0 
                && column + hori[j] < 8 && column + hori[j] >=0
Добавлено через 3 минуты
Цитата Сообщение от DU Посмотреть сообщение
выносите код в функцию, дайте ей говорящее имя и тогда вызывающий код будет более лаконичным:
Я вот тоже так подумал, когда это задание делал. Потом мозг себе ломал с аргументами этих функций

Добавлено через 3 минуты
Кажется. до меня немного доходит.
Вам хватает этого массива для определения вариантов ходов?
C++
1
int shift = {-1, 1, -2, 2};
Limpaku12
0 / 0 / 0
Регистрация: 21.07.2013
Сообщений: 4
21.07.2013, 14:30  [ТС]     Упрощение логического выражения #6
DU,
Это вполне себе вариант, думал о нем, но условие менее громоздким от этого не становится.

Мимино,
Да, хватает. Если x и y - текущие координаты клетки, то для прохождения всех возможных вариантов:

<при таком x>: <проверяются следующие y>
x-1: y-2, y+2
x+1: y-2, y+2
x-2: y-1, y+1
x+2: y-1, y+1

Одинаковые проверки y для разных x видны сразу, вот потому мне и хватает массива shift.

Остановлюсь, пожалуй, на выносе проверки в функцию
Мимино
 Аватар для Мимино
180 / 151 / 5
Регистрация: 22.05.2013
Сообщений: 435
Записей в блоге: 1
21.07.2013, 14:40     Упрощение логического выражения #7
Цитата Сообщение от Limpaku12 Посмотреть сообщение
DU,
Это вполне себе вариант, думал о нем, но условие менее громоздким от этого не становится.

Мимино,
Да, хватает. Если x и y - текущие координаты клетки, то для прохождения всех возможных вариантов:

<при таком x>: <проверяются следующие y>
x-1: y-2, y+2
x+1: y-2, y+2
x-2: y-1, y+1
x+2: y-1, y+1

Одинаковые проверки y для разных x видны сразу, вот потому мне и хватает массива shift.

Остановлюсь, пожалуй, на выносе проверки в функцию
Если я правильно понимаю, Вы генерируете ходы коня из этого массива. Если это так, то это и есть причина таких больших условий для проверки выхода за пределы доски. Ведь если все 8 ходов у Вас предопределены, Вам достаточно проверить только один конкретный ход. Если ходы нужно еще и генерировать при этом, то помимо самого процесса генерации нужно будет еще и проверять каждый ход. Сокращение кода в начале программы ведет в увеличению его в дальнейшем.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.07.2013, 15:09     Упрощение логического выражения
Еще ссылки по теме:

C++ расчёт логического выражения
Вычислить значение логического выражения C++
Расшифровка логического выражения C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Limpaku12
0 / 0 / 0
Регистрация: 21.07.2013
Сообщений: 4
21.07.2013, 15:09  [ТС]     Упрощение логического выражения #8
Решил проблему так:

C++
1
2
3
4
5
6
7
8
9
10
for (int i = 0; i < 2; i++)
   for (int j = 2; j < 4; j++) {
      for (int k = 0, k < 4, k++) {
         if ( (x + shift [k]  < 0) || (x + shift [k] >= boardSize) || (y + shift [k]  < 0) || (y + shift [k] >= boardSize) ) {
            breakFlag = true;
         }
      if (breakFlag) break;
      if (board [ x + shift [i] ] [ y + shift [j] ] != -1) counter++;
      if (board [ x + shift [j] ] [ y + shift [i] ]  != -1) counter++; 
   }
Всем спасибо за помощь! =)
Yandex
Объявления
21.07.2013, 15:09     Упрощение логического выражения
Ответ Создать тему
Опции темы

Текущее время: 06:12. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru