我如何改进此代码以减少使用else语句?

时间:2019-08-07 22:01:11

标签: c++ arrays

我想删除if..elsecompMove函数中的winCon语句,以使用一种算法。

我尝试将if语句条件切换为if(board[z] == 'X' && board[z+1] == 'X' && board[z+2] == 'X' ....),这无效。

我当时在想switch可能会在其中发挥作用,或者我需要找到一种在板上找到相邻方块的方法。

我将从哪里开始?

#include <iostream>
#include <time.h>
using namespace std;

int moves = 0, defBoard[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, playerSpace, x;
char board[] = { '-', '-', '-', '-', '-', '-', '-', '-', '-', }, play;
bool gameOver = false;

void playerMove(), compMove(), print(), winCon(), ticTacToe(), nuclearWar();
int random(int);

int main(){
    cout << "Shall we Play a Game? Y/N" << endl;
    cin >> play;
    if (play == 'N' || play == 'n'){
        return 0;
    }
    else if (play == 'Y' || play == 'y'){
        cout << "1. Global Thermal Nuclear War" << endl << "2. Tic-Tac-Toe" << endl;
        cin >> x;
        switch (x){
            case 1:
                nuclearWar();
                break;
            case 2:
                ticTacToe();
                cout << "Shall we another Play a Game? Y/N" << endl;
                cin >> x;
                break;
        }
    }
    else{
        cout << "Invalid Responce." << endl;
        cout << "Shutting Down..." << endl;
        return 0;
    }
    return 0;
}

void print(){
    cout << "Total Turns: " << moves << endl;
    for (int i = 0; i != 9; ++i){
        if ((i + 1) % 3 == 0){
            cout << board[i] << " " << endl;
        }
        else{
            cout << board[i] << " ";
        }
    }
    cout << endl;
}

void playerMove(){
    cout << "Select Move" << endl;
    cin >> playerSpace;
    if (board[playerSpace - 1] == '-' && board[playerSpace - 1] != 'O'){
        board[playerSpace - 1] = 'X';
    }
    else{
        cout << "Invalid Move " << endl;
        playerMove();
    }
    moves++;
    if (moves == 5){
        print();
    }
    else{
        compMove();
        print();
    }
}

void compMove(){
    if (board[4] == '-'){
        board[4] = 'O';
    }
    else if (board[0] == 'X' && board[1] == 'X' && board[2] == '-'){
        board[2] = 'O';
    }
    else if (board[0] == 'X' && board[2] == 'X' && board[1] == '-'){
        board[1] = 'O';
    }
    else if (board[1] == 'X' && board[2] == 'X' && board[0] == '-'){
        board[0] = 'O';
    }
    else if (board[3] == 'X' && board[4] == 'X' && board[5] == '-'){
        board[5] = 'O';
    }
    else if (board[3] == 'X' && board[5] == 'X' && board[4] == '-'){
        board[4] = 'O';
    }
    else if (board[4] == 'X' && board[5] == 'X' && board[3] == '-'){
        board[3] = 'O';
    }
    else if (board[6] == 'X' && board[7] == 'X' && board[8] == '-'){
        board[8] = 'O';
    }
    else if (board[6] == 'X' && board[8] == 'X' && board[7] == '-'){
        board[7] = 'O';
    }
    else if (board[7] == 'X' && board[8] == 'X' && board[6] == '-'){
        board[6] = 'O';
    }
    else if (board[0] == 'X' && board[3] == 'X' && board[6] == '-'){
        board[6] = 'O';
    }
    else if (board[0] == 'X' && board[6] == 'X' && board[3] == '-'){
        board[3] = 'O';
    }
    else if (board[3] == 'X' && board[6] == 'X' && board[0] == '-'){
        board[0] = 'O';
    }
    else if (board[1] == 'X' && board[4] == 'X' && board[7] == '-'){
        board[7] = 'O';
    }
    else if (board[1] == 'X' && board[7] == 'X' && board[4] == '-'){
        board[4] = 'O';
    }
    else if (board[4] == 'X' && board[7] == 'X' && board[1] == '-'){
        board[1] = 'O';
    }
    else if (board[2] == 'X' && board[5] == 'X' && board[8] == '-'){
        board[8] = 'O';
    }
    else if (board[2] == 'X' && board[8] == 'X' && board[5] == '-'){
        board[5] = 'O';
    }
    else if (board[5] == 'X' && board[8] == 'X' && board[2] == '-'){
        board[2] = 'O';
    }
    else if (board[0] == 'X' && board[5] == 'X' && board[8] == '-'){
        board[8] = 'O';
    }
    else if (board[8] == 'X' && board[5] == 'X' && board[0] == '-'){
        board[0] = 'O';
    }
    else if (board[2] == 'X' && board[5] == 'X' && board[6] == '-'){
        board[6] = 'O';
    }
    else if (board[6] == 'X' && board[5] == 'X' && board[2] == '-'){
        board[2] = 'O';
    }
    else{
        int val = random(9);
        if (board[val - 1] == '-'){
            board[val - 1] = 'O';
        }
        else{
            compMove();
        }
    }
}

void winCon(){
    if (board[0] == 'X' && board[1] == 'X' && board[2] == 'X' || board[3] == 'X' && board[4] == 'X' && board[5] == 'X' ||
        board[6] == 'X' && board[7] == 'X' && board[8] == 'X' || board[0] == 'X' && board[3] == 'X' && board[6] == 'X' ||
        board[1] == 'X' && board[4] == 'X' && board[7] == 'X' || board[2] == 'X' && board[5] == 'X' && board[8] == 'X' ||
        board[0] == 'X' && board[4] == 'X' && board[8] == 'X' || board[2] == 'X' && board[4] == 'X' && board[6] == 'X'){
        cout << "Player Wins! " << endl;
        gameOver = true;
    }
    else if (board[0] == 'O' && board[1] == 'O' && board[2] == 'O' || board[3] == 'O' && board[4] == 'O' && board[5] == 'O' ||
        board[6] == 'O' && board[7] == 'O' && board[8] == 'O' || board[0] == 'O' && board[3] == 'O' && board[6] == 'O' ||
        board[1] == 'O' && board[4] == 'O' && board[7] == 'O' || board[2] == 'O' && board[5] == 'O' && board[8] == 'O' ||
        board[0] == 'O' && board[5] == 'O' && board[8] == 'O' || board[2] == 'O' && board[5] == 'O' && board[6] == 'O'){
        cout << "Computer Wins! " << endl;
        gameOver = true;
    }
    else if (moves == 5){
        cout << "Tie Game. " << endl;
        gameOver = true;
    }
    else{
        gameOver = false;
    }
}

int random(int Max){
    return rand() % Max + 1;
}

void ticTacToe(){
    for (int i = 0; i != 9; ++i){
        if ((i + 1) % 3 == 0){
            cout << defBoard[i] << " " << endl;
        }
        else{
            cout << defBoard[i] << " ";
        }
    }
    srand(time(NULL));
    while (gameOver == false){
        playerMove();
        winCon();
    }
}

void nuclearWar(){
    srand(time(NULL));
    int val = random(4);
    switch (val){
        case 1:
            cout << "A strange game. The only winning move is not to play. How about a nice game of chess?" << endl;
            break;
        case 2:
            cout << "I've come to the conclusion that your new defense system sucks." << endl;
            break;
        case 3:
            cout << "Flush the bombers, get the subs in launch mode. We are at DEFCON 1." << endl;
            break;
        case 4:
            cout << " Is it a game... or is it real?" << endl;
            break;
    }
}

2 个答案:

答案 0 :(得分:0)

您可能首先注意到winCon中的类似代码:

void winCon(){
        if (board[0] == 'X' && board[1] == 'X' && board[2] == 'X' || board[3] == 'X' && board[4] == 'X' && board[5] == 'X' ||
            board[6] == 'X' && board[7] == 'X' && board[8] == 'X' || board[0] == 'X' && board[3] == 'X' && board[6] == 'X' ||
            board[1] == 'X' && board[4] == 'X' && board[7] == 'X' || board[2] == 'X' && board[5] == 'X' && board[8] == 'X' ||
            board[0] == 'X' && board[4] == 'X' && board[8] == 'X' || board[2] == 'X' && board[4] == 'X' && board[6] == 'X'){
            cout << "Player Wins! " << endl;
            gameOver = true;
        }
        else if (board[0] == 'O' && board[1] == 'O' && board[2] == 'O' || board[3] == 'O' && board[4] == 'O' && board[5] == 'O' ||
            board[6] == 'O' && board[7] == 'O' && board[8] == 'O' || board[0] == 'O' && board[3] == 'O' && board[6] == 'O' ||
            board[1] == 'O' && board[4] == 'O' && board[7] == 'O' || board[2] == 'O' && board[5] == 'O' && board[8] == 'O' ||
            board[0] == 'O' && board[5] == 'O' && board[8] == 'O' || board[2] == 'O' && board[5] == 'O' && board[6] == 'O'){
            cout << "Computer Wins! " << endl;
            gameOver = true;
        }
        else if (moves == 5){
            cout << "Tie Game. " << endl;
            gameOver = true;
        }
        else{
            gameOver = false;
        }
    }

类似,但有错字。让我们通过执行专用功能来解决该问题:

bool has_won(const char (&board)[9], char p)
{
    return board[0] == p && board[1] == p && board[2] == p
        || board[3] == p && board[4] == p && board[5] == p
        || board[6] == p && board[7] == p && board[8] == p
        || board[0] == p && board[3] == p && board[6] == p
        || board[1] == p && board[4] == p && board[7] == p
        || board[2] == p && board[5] == p && board[8] == p
        || board[0] == p && board[4] == p && board[8] == p
        || board[2] == p && board[4] == p && board[6] == p;
}

void winCon(){
    if (has_won(board, 'X')) {
        cout << "Player Wins! " << endl;
        gameOver = true;
    }
    else if (has_won(board, 'O')){
        cout << "Computer Wins! " << endl;
        gameOver = true;
    }  else if (moves == 5){
        cout << "Tie Game. " << endl;
        gameOver = true;
    } else{
        gameOver = false;
    }
}

然后使用has_won函数,有几种拆分方法。

我们可能会注意到我们先水平检查,然后垂直检查2条对角线。

我们可能会注意到三元组遵循我们可能分解的某些规则/系列。

所以我们可以这样做:

bool three_in_a_row(const char (&board)[9], char p, int origin, int dir)
{
#if 1
    return board[origin] == p && board[origin + dir] == p && board[origin + 2 dir] == p;
#else
    for (int i = 0; i != 3; ++i) {
        if (board[origin + i * dir] != p) {
            return false;
        }
    }
    return true;
#endif
}
// Is three_in_a_row(board, p, 0, 3) "better" than board[0] == p && board[3] == p && board[6] == p

bool has_won(const char (&board)[9], char p)
{
    // horizontals and verticals
    for (int i = 0; i != 3; ++i) {
        if (three_in_a_row(board, p, 3 * i, 1) // 3 * i, 3 * i + 1, 3 * i + 2
            || three_in_a_row(board, p, i, 3)) { // i, i + 3, i + 6
            return true;
        }
    }

    // both diagonals
    return three_in_a_row(board, p, 0, 4)  // 0 4 8
        || three_in_a_row(board, p, 2, 2); // 2 4 6
}

尽管第一次分解可使代码更简洁,但第二次尝试尚不清楚。 (此外,我们添加了一些隐藏的依赖项:对起点/方向应该正确,否则我们可能会超出范围)

答案 1 :(得分:0)

通过使用行和列索引将board更改为二维数组以访问单个单元格,并更智能地跟踪X和O使用多少个单元格,可以大大简化代码。

尝试更多类似的方法:

#include <iostream>
#include <ctime>
using namespace std;

struct counts{
    int NumX;
    int NumO;

    void reset(){
        NumX = NumO = 0;
    }

    void added(char which){
        switch (which){
            case 'X': ++NumX; break;
            case 'O': ++NumO; break;
        }
    }
};

int moves, number;
char board[3][3], letter;
counts rows[3], cols[3], diagonals[2];
int cellsAvailable[9], numAvailable;

void playerMove();
void compMove();
void print();
bool gameOver();
void ticTacToe();
void nuclearWar();
int random(int);
void setCell(int, int, char);

int main(){
    srand(time(NULL));

    cout << "Shall we Play a Game? Y/N" << endl;

    do {
        cin >> letter;

        if (letter == 'N' || letter == 'n'){
            break;
        }

        if (letter != 'Y' && letter != 'y'){
            cout << "Invalid Response." << endl;
            cout << "Shutting Down..." << endl;
            break;
        }

        cout << "1. Global Thermal Nuclear War" << endl
             << "2. Tic-Tac-Toe" << endl;
        cin >> number;

        switch (number){
            case 1:
                nuclearWar();
                break;
            case 2:
                ticTacToe();
                break;
            default:
                cout << "Invalid Game." << endl;
                break;
        }

        cout << "Shall we Play another Game? Y/N" << endl;
    }
    while (true);

    return 0;
}

void print(){
    cout << "Total Turns: " << moves << endl;
    for (int row = 0; row < 3; ++row){
        for (int col = 0; col < 3; ++col){
            cout << board[row][col] << " ";
        }
        cout << endl;
    }
    cout << endl;
}

void setCell(int row, int col, char which){
    board[row][col] = which;

    rows[row].added(which);
    cols[col].added(which);

    if (row == col){
        diagonals[0].added(which);
    }

    if ((row == 0 && col == 2) ||
        (row == 1 && col == 1) ||
        (row == 2 && col == 0)){
        diagonals[1].added(which);
    }

    int val = (row * 3) + col;
    for(int i = 0; i < numAvailable; ++i){
        if (cellsAvailable[i] == val){
            for(int j = i + 1; j < numAvailable; ++j){
                cellsAvailable[j-1] = cellsAvailable[j];
            }
            --numAvailable;
            break;
        }
    }
}

void playerMove(){
    do {
        cout << "Select Move" << endl;
        cin >> number;

        if (number >= 1 && number <= 9){
            --number;
            int row = number / 3;
            int col = number % 3;
            if (board[row][col] == '-'){
                setCell(row, col, 'X');
                break;
            }
        }
        cout << "Invalid Move" << endl;
    }
    while (true);
}

void compMove(){
    for (int row = 0; row < 3; ++row){
        if (rows[row].NumX == 2 && rows[row].NumO == 0){
            for(int col = 0; col < 3; ++col){
                if (board[row][col] == '-'){
                    setCell(row, col, 'O');
                    break;
                }
            }
            return;
        }
    }

    for (int col = 0; col < 3; ++col){
        if (cols[col].NumX == 2 && cols[col].NumO == 0){
            for(int row = 0; row < 3; ++row){
                if (board[row][col] == '-'){
                    setCell(row, col, 'O');
                    break;
                }
            }
            return;
        }
    }

    if (diagonals[0].NumX == 2 && diagonals[0].NumO == 0){
        for(int row = 0; row < 3; ++row){
            for(int col = 0; col < 3; ++col){
                if (board[row][col] == '-'){
                    setCell(row, col, 'O');
                    break;
                }
            }
        }
        return;
    }

    if (diagonals[1].NumX == 2 && diagonals[1].NumO == 0){
        for(int row = 0; row < 3; ++row){
            for(int col = 2; col >= 0; --col){
                if (board[row][col] == '-'){
                    setCell(row, col, 'O');
                    break;
                }
            }
        }
        return;
    }

    int val = cellsAvailable[random(numAvailable)];
    setCell(val / 3, val % 3, 'O');
}

bool gameOver(){
    for(int i = 0; i < 3; ++i){
        if (rows[i].NumX == 3 || cols[i].NumX == 3 || (i < 2 && diagonals[i].NumX == 3)){
            cout << "Player Wins!" << endl;
            return true;
        }
        if (rows[i].NumO == 3 || cols[i].NumO == 3 || (i < 2 && diagonals[i].NumO == 3)){
            cout << "Computer Wins!" << endl;
            return true;
        }
    }

    if (moves == 5){
        cout << "Tie Game." << endl;
        return true;
    }

    return false;
}

int random(int Max){
    return rand() % Max;
}

void ticTacToe(){
    for (int row = 0; row < 3; ++row){
        for (int col = 0; col < 3; ++col) {
            board[row][col] = '-';
            cout << ((row * 3) + col) + 1 << " ";
        }
        cout << endl;
    }

    for (int i = 0; i < 3; ++i){
        rows[i].reset();
        cols[i].reset();
    }
    for (int i = 0; i < 2; ++i){
        diagonals[i].reset();
    }

    for(int i = 0; i < 9; ++i){
        cellsAvailable[i] = i;
    }
    numAvailable = 9;

    moves = 0;

    do{
        playerMove();
        if (++moves != 5){
            compMove();
        }
        print();
    }
    while (!gameOver());
}

void nuclearWar(){
    int val = random(4) + 1;
    switch (val){
        case 1:
            cout << "A strange game. The only winning move is not to play. How about a nice game of chess?" << endl;
            break;
        case 2:
            cout << "I've come to the conclusion that your new defense system sucks." << endl;
            break;
        case 3:
            cout << "Flush the bombers, get the subs in launch mode. We are at DEFCON 1." << endl;
            break;
        case 4:
            cout << " Is it a game... or is it real?" << endl;
            break;
    }
}