【问题标题】:Print a matrix of alternating X's and O's given column and row constraints?在给定的列和行约束下打印交替 X 和 O 的矩阵?
【发布时间】:2021-08-24 02:23:48
【问题描述】:

在给定以下参数的情况下,我正在尝试编写一个打印 X 和 O 矩阵的算法:

int numRows
int numCols
int charsPerCol
int charsPerRow

例如打电话

printXOMatrix(int charsPerCol, int charsPerRow, int numCols, int numRows);

带参数

printXOMatrix(3,2,15,8);

将导致以下内容被打印到标准输出:

XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
OOOXXXOOOXXXOOO
OOOXXXOOOXXXOOO
XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
OOOXXXOOOXXXOOO
OOOXXXOOOXXXOOO

到目前为止,这是我的代码,如果列数/每列的字符数不同,它似乎可以正确打印,但例如在以下情况下会失败:

printXOMatrix(2,2,8,8);

以下内容被打印到标准输出:

XXOOXXOO
OOXXOOXX
OOXXOOXX
XXOOXXOO
XXOOXXOO
OOXXOOXX
OOXXOOXX
XXOOXXOO

如何处理这种极端情况/清理我的代码?这是我目前所拥有的:

#include <stdio.h>

void getXAndOGrid(int charsPerCol, int charsPerRow, int numCols, int numRows) {
    char c = 'X';
        for (int i=1; i<=(numCols*numRows); i++) {
            // if current index is divisible by the columns (new row)
            if (i % numCols == 0) {
                // print character, then newline
                printf("%c\n", c);
                // if current index is divisible by number of columns times num of chars in column
                if (i % (numCols * charsPerRow) == 0) {
                    if (c == 'O') {
                        c = 'X';
                    } else {
                        c = 'O';
                    }
                }
            // else if current index is divisible by num in row before it alternates
            // and is not divisible by number of columns
            } else if (i % charsPerCol == 0) {
                printf("%c", c);
                if (c == 'O') {
                    c = 'X';
                } else {
                    c = 'O';
                }
            } else {
                printf("%c", c);
            }
        }
}

int main() {
    getXAndOGrid(3,2,15,8);
    return 0;
}

【问题讨论】:

  • 您已经在最初声明函数的方式和实际实现方式之间交换了顺序或参数。是哪个?
  • @selbie 感谢您告诉我,已修复。

标签: c++ c algorithm


【解决方案1】:

问题是您错过了一个案例。您处理了表格切换的情况,条件为:if (i % (numCols * charsPerRow) == 0),但您还没有处理 doesn't 的情况。所以我添加了另一个条件:

if (i % (numCols * charsPerRow) == 0) 
{

    if ((numCols / charsPerCol)%2 == 1)
    {
        if (c == 'O')
        {
            c = 'X';
        }
        else
        {
            c = 'O';
        }
    }
}
else
{
    if ((numCols / charsPerCol)%2 == 0)
    {
        if (c == 'O')
        {
            c = 'X';
        }
        else
        {
            c = 'O';
        }
    }
}

所以,如果(numCols / charsPerCol) 是奇数,例如XXOOXXOOXX,则不需要从X 切换 O,否则是(例如XXOOXXOO,现在需要切换c来自O -> X)。

当达到初始条件i % (numCols * charsPerRow) == 0 时,情况正好相反。

完整代码:

#include <iostream>
using namespace std;

void getXAndOGrid(int charsPerCol, int charsPerRow, int numCols, int numRows) {
    char c = 'X';
        for (int i=1; i<=(numCols*numRows); i++) {
            // if current index is divisible by the columns (new row)
            if (i % numCols == 0) {
                // print character, then newline
                printf("%c\n", c);

                // if current index is divisible by number of columns times num of chars in column
                if (i % (numCols * charsPerRow) == 0) {

                    if ((numCols / charsPerCol)%2 == 1)
                    {
                        if (c == 'O') {
                        c = 'X';
                        } else {
                            c = 'O';
                        }
                    }
                }
                else
                {
                    //cerr << c << endl;
                    if ((numCols / charsPerCol)%2 == 0)
                    {
                        if (c == 'O') {
                        c = 'X';
                        } else {
                            c = 'O';
                        }
                    }
                }
            // else if current index is divisible by num in row before it alternates
            // and is not divisible by number of columns
            }
            else if (i % charsPerCol == 0) {
                printf("%c", c);
                if (c == 'O') {
                    c = 'X';
                } else {
                    c = 'O';
                }
            }
            else {
                printf("%c", c);
            }
        }
}

int main() {
    getXAndOGrid(2,2,8,8);
    return 0;
}

输出(你的情况):

XXOOXXOO
XXOOXXOO
OOXXOOXX
OOXXOOXX
XXOOXXOO
XXOOXXOO
OOXXOOXX
OOXXOOXX

输出(getXAndOGrid(3,3,15,15);):

XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
OOOXXXOOOXXXOOO
OOOXXXOOOXXXOOO
OOOXXXOOOXXXOOO
XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
OOOXXXOOOXXXOOO
OOOXXXOOOXXXOOO
OOOXXXOOOXXXOOO
XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX
XXXOOOXXXOOOXXX

P.S : IMO,你的代码有很多重复的代码,如果实现一个函数不是更干净吗?

void switchC(char &c)
{
    if (c == 'O') { c = 'X';} else {c = 'O';}
}

void getXAndOGrid(int charsPerCol, int charsPerRow, int numCols, int numRows) {
    char c = 'X';
    for (int i=1; i<=(numCols*numRows); i++) {
        if (i % numCols == 0) {
            printf("%c\n", c);
            if (i % (numCols * charsPerRow) == 0) {
                if ((numCols / charsPerCol)%2 == 1) {switchC(c);}
            }
            else {
                if ((numCols / charsPerCol)%2 == 0) {switchC(c);}
            }
        }
        else if (i % charsPerCol == 0) { printf("%c", c); switchC(c);}
        else { printf("%c", c);}
    }
}

P.P.S : @Skizz 和 @selbie 更加紧凑。

【讨论】:

    【解决方案2】:

    您的代码非常复杂,因为您要逐个字符地打印,使用初始化为 1 而不是 0 的 for 循环索引值,并尝试在单个循环中打印整个内容。

    这是一种更简洁的方法。有两个独特的行要打印。一个以X 开头,一个以O 开头。有一个 for 循环来构建每种线型。然后另一个循环打印每一行。

    你怎么看这个?下面的代码使用 C++,但如果您需要纯 C,请将 new/delete 调用替换为 malloc 和 free,如 cmets 中所示:

    void printXOMatrix(int numRows, int numCols, int charsPerCol, int charsPerRow)
    {
        char* primary = new char[numCols + 1];    // malloc(sizeof(char)*(numcols+1))
        char* opposite = new char[numCols + 1];   // malloc(sizeof(char)*(numcols+1))
    
        for (int col = 0; col < numCols; col++)
        {
            char ch = (col % (charsPerCol * 2) < charsPerCol) ? 'X' : 'O';
            primary[col] = ch;
            opposite[col] = (ch == 'X') ? 'O' : 'X';
        }
        primary[numCols] = '\0';
        opposite[numCols] = '\0';
    
        for (int row = 0; row < numRows; row++)
        {
            char* line = (row % (charsPerRow * 2) < charsPerRow) ? primary : opposite;
            std::cout << line << std::endl; // printf("%s\n", line);
        }
        delete[] primary;    // free(primary)
        delete[] opposite;   // free(opposite)
    }
    

    【讨论】:

      【解决方案3】:

      好吧,在确定代码与 selbie 所说的不一致之后,问题似乎是当您到达行尾时,您没有将 c 重置回行首时的状态!

      但问题应该是:你为什么要写这么多代码?以下内容完全相同(好吧,除了正确处理边缘情况!):-

      void PrintMatrix (int charsPerCol, int charsPerRow, int numCols, int numRows)
      {
        for (int y = 0 ; y < numRows ; ++y)
        {
          for (int x = 0 ; x < numCols ; ++x)
          {
            printf ((((x / charsPerCol) & 1) ^ ((y / charsPerRow) & 1)) != 0 ? "o" : "x");
          }
      
          printf ("\n");
        }
      }
      

      【讨论】:

      • 我喜欢这个答案。它比我的更紧凑 - 这也是我想要优化的。
      • 如果你真的不喜欢打字,那么你总是可以将第一个 printf 的参数替换为 "%c", 80 - ((x / charsPerCol ^ y / charsPerRow) &amp; 1) | 8,但这开始看起来像诡异的魔法
      猜你喜欢
      • 2021-11-09
      • 2013-07-25
      • 1970-01-01
      • 1970-01-01
      • 2015-01-10
      • 2020-10-23
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多