【问题标题】:Smiles in output C++输出 C++ 中的微笑
【发布时间】:2015-02-20 14:52:36
【问题描述】:

我现在正在写井字游戏,但我遇到了一个非常有趣的问题。该程序运行良好,但问题在于井字游戏矩阵。最后一个元素(最后一行,最后一列)是一个微笑,它有时会发生变化。有时是笑的微笑,也可能是一颗心。怎么了?

整个代码:

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <stdlib.h>
using namespace std;
char matrix[3][3];
int orow, ocolumn, xrow, xcolumn;
int drawcounter = 0;
void paint() {
    for (int i = 1; i < 4; i++) {
        for (int j = 1; j < 4; j++)
            matrix[i][j] = '_';
    }
}
void board() {
    for (int i = 1; i < 4; i++)
        for (int j = 1; j < 4; j++) {
            if (i != 1 && j == 1)
                cout << endl;
            cout << matrix[i][j] << " ";
        }

    cout << endl;
    //cout << matrix[3][3] << endl;

}

void action() {
    while (0 == 0) {
        puts("Time for player X. Enter index");
        cin >> xcolumn >> xrow;
        matrix[xcolumn][xrow] = 'X';
        drawcounter += 1;
        if (drawcounter == 9) {
            puts("It's a draw.");
            break;
        }
        board();
        cout << endl;
        if ((matrix[1][1] == 'X' && matrix[2][2] == 'X' && matrix[3][3] == 'X') || (matrix[1][3] == 'X' && matrix[2][2] == 'X' && matrix[3][1] == 'X')) {
            puts("X Wins! Congrats X!");
            break;
        }
        if ((matrix[1][1] == 'X' && matrix[1][2] == 'X' && matrix[1][3] == 'X') || (matrix[2][1] == 'X' && matrix[2][2] == 'X' && matrix[2][3] == 'X') || (matrix[3][1] == 'X' && matrix[3][2] == 'X' && matrix[3][3] == 'X')) {
            puts("X Wins! Congrats X!");
            break;
        }
        if ((matrix[1][1] == 'X' && matrix[2][1] == 'X' && matrix[3][1] == 'X') || (matrix[1][2] == 'X' && matrix[2][2] == 'X' && matrix[3][2] == 'X') || (matrix[1][3] == 'X' && matrix[2][3] == 'X' && matrix[3][3] == 'X')) {
            puts("X Wins! Congrats X!");
            break;
        }
        puts("Time for player O. Enter index");
        cin >> ocolumn >> orow;
        matrix[ocolumn][orow] = 'O';
        drawcounter += 1;
        board();
        cout << endl;
        if ((matrix[1][1] == 'O' && matrix[2][2] == 'O' && matrix[3][3] == 'O') || (matrix[1][3] == 'O' && matrix[2][2] == 'O' && matrix[3][1] == 'O')) {
            puts("O Wins! Congrats O!");
            break;
        }
        if ((matrix[1][1] == 'O' && matrix[1][2] == 'O' && matrix[1][3] == 'O') || (matrix[2][1] == 'O' && matrix[2][2] == 'O' && matrix[2][3] == 'O') || (matrix[3][1] == 'O' && matrix[3][2] == 'O' && matrix[3][3] == 'O')) {
            puts("O Wins! Congrats O!");
            break;
        }
        if ((matrix[1][1] == 'O' && matrix[2][1] == 'O' && matrix[3][1] == 'O') || (matrix[1][2] == 'O' && matrix[2][2] == 'O' && matrix[3][2] == 'O') || (matrix[1][3] == 'O' && matrix[2][3] == 'O' && matrix[3][3] == 'O')) {
            puts("O Wins! Congrats O!");
            break;
        }
    }
}
int main() {
    paint();
    board();
    action();
    system("pause");
    return 0;
}

输出图片:

【问题讨论】:

  • 控制台窗口效果是因为您输出的字节值
  • “你的输出中是那个UB,还是你很高兴见到我?”

标签: c++


【解决方案1】:

C/C++ 中的数组索引从 0 开始,而不是从 1 - 所以你必须重写你的代码:

void paint() {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++)
            matrix[i][j] = '_';
    }
}

void board() {
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++) {
            if (i != 0 && j == 0)
                cout << endl;
            cout << matrix[i][j] << " ";
        }

    cout << endl;
    //cout << matrix[3][3] << endl;    
}

这里实际上发生了什么,详细:当你定义你的数组时,你应该记住索引从 0 开始,所以例如当你声明一个包含 3 个元素的数组时,matrix[3],它不会像 @987654325 @、matrix[2]matrix[3],而是 matrix[0]matrix[1]matrix[2]

因此,在这种情况下,您将超出数组边界 - 它是分配给数组的内存区域之外的“这里是龙”区域。所以基本上你在这里使用原始内存,在你的情况下它包含一个笑脸的字符代码(这就是为什么它每次都不同 - 因为在这个区域没有确定内存内容 - 例如,你甚至可以尝试得到一个值matrix[123],尽管它的大小只有 3 个元素 - 结果是一个未定义的随机值)。

您应该记住,在这方面,C/C++ 数组的行为与指针非常相似——您甚至可以说它是一回事。

【讨论】:

  • 非常感谢,但是当我开始编写井字游戏时,我希望当我输入:1 2 时,它会完美运行(1 列,2 行)。我在想输入 0 1, 0 2 是“丑陋的”。所以,好的,我将编辑我的代码。谢谢。
  • 您可以坚持使用从 1 开始的索引,您只需要声明一个更大的数组 - 即 char matrix[4][4] 用于 3x3 游戏板。
  • @GùrìCôppérfîéld:只需从输入的数字中减去 1!
【解决方案2】:

在 C++ 中,数组从 0 开始索引。所以在 paint() 中的循环中

for(int i = 1; i < 4; ++i) // out of bounds when `i = 3`

你有一个越界访问,matrix 被声明为

char matrix[3][3]; 

您必须将所有此类循环替换为从 0 到 3 的循环。另外,您的 if 条件可能是错误的

if ((matrix[1][6] == 'X' && matrix[2][7] .... // 6 and 7 ?!?! 

因为行/列索引不能大于 2

【讨论】:

  • @GùrìCôppérfîéld StackOverflow 遵循的问答格式要求问题实际上是一个问题(包括没有答案),并且答案被投票给顶部/接受,以便未来的人们立即当他们阅读完问题并确定它适合他们的情况时,请查看“正确”答案。将解决方案放在问题中是一个好主意,最好的答案可以隐藏在 10 页深的论坛中,但 SO 不会因此受到影响。
【解决方案3】:
char matrix[3][3];

[...]

matrix[3][3] == 'O'

这行不通。数组索引从 0 开始。所以你声明了一个大小为 3 的数组,然后访问它的第 4 个元素。这是未定义的行为。这意味着任何事情都可能发生,包括崩溃或打印看似随机的字符。

请注意,使用这样的原始数组可能会引起一两个人的注意。如果您希望能够动态确定矩阵大小(例如通过用户输入),无论如何您都需要使用std::vector。如果在概念上确实需要在编译时知道大小(诚然,这样的游戏可能就是这种情况),请考虑使用std::array,或者至少了解它的语法和好处。

【讨论】:

  • 哦,对于像这样的固定大小的数组,原始数组是可以的。我不太喜欢std::array(这将是固定大小数组的标准库选择)。例如。使用一些元组函数来获得编译时大小对我来说是违反直觉的,存在 create-it-with-size-from-initializer 问题等。我认为原始数组就可以了。
  • @Cheersandhth.-Alf:就我个人而言,我认为多维原始数组在代码中阅读起来非常不愉快。使用std::array,我的头脑似乎更容易消化语法。我将编辑答案以反映这是一个主观方面的事实。
  • 只需定义template&lt; int n, Type T &gt; using Array = T[n];。然后写例如Array&lt; 3, Array&lt; 3, int &gt; &gt; matrix;;-)
【解决方案4】:

也许您正试图将 1 存储在 char 数组中为

#include<iostream>
using namespace std;
int main()
{
    char n=1;
    cout << n;
    return 0;
 }

输出将是一个笑脸

【讨论】:

  • 你看过其他答案了吗?你确定这会带来一些新的东西吗?不过,并不是说这是不正确的。
  • 我刚刚回答了这个问题,没有看到任何答案:)
  • 这是因为几天前我正在研究吃豆人,这就是为什么我只是快速回答问题而没有阅读其他人的想法:) 对不起,如果你不喜欢我的回答 :)
猜你喜欢
  • 1970-01-01
  • 2016-06-02
  • 2011-08-19
  • 1970-01-01
  • 2018-01-27
  • 2018-12-14
  • 1970-01-01
  • 2019-02-11
  • 2017-02-28
相关资源
最近更新 更多