车子移动功能没有发现中断
Rook movement function not finding interruptions
我正在尝试编写一个函数来检查黑王是否被白车控制。当我尝试搜索车和王之间是否有棋子时出现问题。
void rook_white(piece A[]) // does WR check BK
{
cout << "Found White Rook ";
int k_x; // BK'S x coordinate
int k_y; // BK's y coordinate
bool check = false;
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x-x][m_y] == 'k') // Moving Left
{
k_x=m_x;
k_y=m_y;
goto al_1;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x+x][m_y] == 'k') // Moving Right
{
k_x=m_x;
k_y=m_y;
goto al_2;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y-y] == 'k') // Moving Up
{
k_x=m_x;
k_y=m_y;
goto al_3;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y+y] == 'k') // Moving Down
{
k_x=m_x;
k_y=m_y;
goto al_4;
}
}
}
al_1:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x-x][m_y] == '*') // Checking left
{
goto loop_exit;
}
}
}
al_2:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x+x][m_y] == '*') // Checking Right
{
goto loop_exit;
}
}
}
al_3:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y-y] == '*') // Checking Up
{
goto loop_exit;
}
}
}
al_4:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y+y] == '*') // Checking Down
{
goto loop_exit;
}
}
}
loop_exit:
check = false;
if (check == true)
{
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
}
}
该函数在 x 和 y 轴上搜索国王在哪里。然后它进入特定算法(al_1、al_2、...),在该算法中搜索国王和车之间是否有任何东西。
输入文件大致如下:
********
***k****
********
***q****
********
********
***R****
********
这不应该什么都不输出,而
********
***k****
********
********
********
********
***R****
********
应该输出"Black is in check by rook "。 (t_i 是正在检查的板的编号)
A[t_i]是一个struct数组,struct块由char field[8][8]组成。
我使用结构体是因为我要检查的板子数量不受限制。
k_x和k_y是王坐标。
m_x 和 m_y 是全局变量,从找到一个片段的搜索功能中传递过来
这是带有 int main()
的程序本身
#include <iostream>
#include <fstream> // chess
#include <cstdlib>
using namespace std; // PROGRAM CHECKS FOR CHESS CHEKS
const char FVD[]="5_input.txt"; // **************************************************
const char FVR[]="5_output.txt"; // P - white pawn (WP) p - black pawn (BP)
//--- // R - white rook (WR) r - black rook (BR)
//--- // B - white bishop (WB) b - black bishop (BB)
int m_i=0; // max i // N - white knight (WN) n - black knight (BN)
int m_x=0; // // Q - white queen (WQ) q - black queen (BQ)
int m_y=0; // // K - white king (WK) k - black king (BK)
int t_i=0; // // **************************************************
struct piece
{
char field[8][8];
};
void read(piece A[])
{
ifstream fd(FVD);
int i=0;
m_i=0;
while(!fd.eof())
{
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
fd >> A[i].field[x][y];
}
}
fd.ignore();
i++;
m_i=i;
}
fd.close();
}
/// ----------------------------------------------BLACK KING IS IN CHECK--------------------------------------------------------------
void rook_white(piece A[]) // does WR check BK
{
cout << "Found White Rook ";
int k_x; // BK'S x coordinate
int k_y; // BK's y coordinate
bool check = false;
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x-x][m_y] == 'k') // Moving Left
{
k_x=m_x;
k_y=m_y;
goto al_1;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x+x][m_y] == 'k') // Moving Right
{
k_x=m_x;
k_y=m_y;
goto al_2;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y-y] == 'k') // Moving Up
{
k_x=m_x;
k_y=m_y;
goto al_3;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y+y] == 'k') // Moving Down
{
k_x=m_x;
k_y=m_y;
goto al_4;
}
}
}
al_1:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x-x][m_y] == '*') // Checking left
{
goto loop_exit;
}
}
}
al_2:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x+x][m_y] == '*') // Checking Right
{
goto loop_exit;
}
}
}
al_3:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y-y] == '*') // Checking Up
{
goto loop_exit;
}
}
}
al_4:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y+y] == '*') // Checking Down
{
goto loop_exit;
}
}
}
loop_exit:
check = false;
if (check == true)
{
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
}
}
///-----------------------------------------SEARCHING FOR THE CHECKS // CALLING FUNCTIONS --------------------------------------------
void search(piece A[]) // searches for piece and calls a function related to it
{
for(int i=0; i<m_i-1; i++)
{
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if (A[i].field[x][y]=='R')
{
t_i=i;
m_x=x;
m_y=y;
rook_white(A);
}
}
}
}
}
int main()
{
piece A[10];
remove(FVR); // clears the output before inputting new data because of ios::app
read(A);
search(A);
ofstream fr(FVR);
fr << "Done";
return 0;
}
我会做我平时不做的事情 -- 我会给你一个完整的往返(因为我喜欢)。
你从一个 main()
开始,它应该读取任意数量的字段(但实际上在 11 日崩溃),以及一个 search()
函数,它旨在最终遍历所有可能的棋子...但是您的程序在检查第一块白车时失败了。
您也从 C 开始,然后顺势引入 C++,实际上让事情变得比必要的更困难。
所以让我们trim记下来。 首先,我们会将 "minimal" 放入您的示例代码中。
让我们用<vector>
代替二维数组。向量是 C++ 中 最有用的东西之一,几乎没有理由再使用 C 风格的数组(除了 C API 兼容性)。 =64=]
#include <vector>
#include <iostream>
typedef std::vector< std::vector< char > > Field;
Field
现在是 char
向量的向量的别名。这与二维数组(包括 [][]
寻址)基本相同,但它有一些您很快就会看到的优点。
您的 rook_white()
(如您设计的那样)需要 一个 字段,以及车的 X 和 Y 坐标。请允许我稍微调整一下您的函数原型——我喜欢更具表现力的标识符名称。
void rook_white( Field const & field, unsigned rook_x, unsigned rook_y );
搜索并删除 A[t_i].
,我们现在只处理那个字段。将 m_x
搜索并替换为 rook_x
,将 m_y
替换为 rook_y
。不是太难。同时替换:
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
有:
std::cout << "Black is in check by rook" endl;
现在我们不用理会文件 I/O.
现在,我们需要设置一个字段,但是我们暂时不需要从文件中读取它。实际检查工作后,您可以扩展代码。
int main()
{
Field field( 8, std::vector< char >( 8, '*' ) );
std::vector< char >( 8, '*' )
创建一个 8 '8'
个字符的临时向量。 Field field( 8, /*...*/ );
创建一个 Field
,其中包含该临时向量的 8 个副本。
现在让我们放置你的棋子。
unsigned rook_x = 3;
unsigned rook_y = 6;
field[rook_x][rook_y] = 'R';
unsigned king_x = 3;
unsigned king_y = 1;
field[king_x][king_y] = 'k';
此时我意识到 你的示例代码在 search()
中混淆了 "X" 和 "Y" 坐标(报告 X 处的车= 6,Y = 3),但没关系。那不是你问题的根源。
我们现在有了字段和坐标来调用您的函数。
rook_white( field, rook_x, rook_y );
return 0;
}
这种编写 main()
的方式并没有真正反映您的最终应用程序应该做什么,而是为特定功能设置测试,称为 测试驱动程序。我们刚刚从您的示例中删除了 50 多行不必要的代码,消除了各种不相关的潜在问题。
现在,让我们看看 rook_white()
,好吗?
因为我们现在有一个 vector< vector< char > >
而不是 "dumb" 数组,我们可以做一些漂亮的事情:用 .at()
替换 []
访问。原因?如果 []
的索引越界,它可能会也可能不会使程序崩溃。如果 .at()
的索引越界,它 将 抛出异常。
所以,虽然 .at()
(有点)慢并且通常不在生产代码中使用,但我建议初学者使用它,因为它不允许 "hide".[=64= 的错误]
此时你应该眉头一挑,心想,"why is he suggesting this?"。然后你应该看看你的循环,并且...
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(field[rook_x-x][rook_y] == 'k')
{
k_x=rook_x;
k_y=rook_y;
goto al_1;
}
}
}
是的,没错。您对您的字段有 越界访问 。
rook_x
/ rook_y
在场地中间的某个地方,但如果找不到国王,您坚持访问 [rook_x - 7][rook_y]
之前的任何内容。那是您原始代码中的负索引。由于我将坐标更改为 unsigned
(它会溢出并变得 非常大 ),你会遇到段错误崩溃(如果幸运的话)。那实际上是无意的;我只是声明不能为负的东西 unsigned
by habbit.
但这就是为什么我建议您在学习期间使用 vector<>
的 .at()
方法:尽早失败并尽可能大声地失败。 异常优于未定义的行为。
此外,你(在所有这些循环中)总是循环x
和y
,但只使用 循环中 两个变量中的一个。这是很多 浪费的时钟周期 。这不会破坏您的逻辑只是偶然...
此时您可能想要完全重新编写代码。但是等等,还有更多。
如果您 "move left" 在您的第一个循环中找到国王,那么您 goto al_1
。在那里你循环(再次使用两个循环计数器之一)来检查中间部分。
第一个循环是 x == 0
,检查 [rook_x - 0][rook_y]
... 猜猜看,你发现白车正在介入,因为那里在该字段中没有 '*'
,因此您跳转到 loop_exit
...
即使你没有犯那个错误,你也会从那个循环中出来并输入 al_2
,同时检查车的所有剩余方向...
即使这一切都不会发生,无论发生什么,你最终运行会变成这样:
loop_exit:
check = false;
if (check == true)
{
std::cout << "Black is in check by rook \n";
}
嗯,check == true
永远不会发生,对吧?
在这一点上我引用你的评论之一...
...I just don't understand [switch statements] and couldn't really wrap my head around on how to write them as switch.
我的建议?我完全理解你为什么要尽快写 "something real" 。教科书很无聊。但是你真的应该多花一些时间"wrapping your head around"基本概念。 C 和 C++ 是使用 "trial & error" 方法 学习它们的语言。有太多的事情可以而且将会出错。
We have a list of recommended textbooks, if the one you have isn't to your tastes.
如果你在真正掌握正确的基础知识之前尝试了太多的东西(比如国际象棋程序),那么你可能遇到的任何问题的答案最终都会比舒适的时间长很多,无论是写(如果有人喜欢它)并让你消化。
请:
不要使用 goto
除非你绝对肯定地知道你在做什么。
我正在尝试编写一个函数来检查黑王是否被白车控制。当我尝试搜索车和王之间是否有棋子时出现问题。
void rook_white(piece A[]) // does WR check BK
{
cout << "Found White Rook ";
int k_x; // BK'S x coordinate
int k_y; // BK's y coordinate
bool check = false;
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x-x][m_y] == 'k') // Moving Left
{
k_x=m_x;
k_y=m_y;
goto al_1;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x+x][m_y] == 'k') // Moving Right
{
k_x=m_x;
k_y=m_y;
goto al_2;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y-y] == 'k') // Moving Up
{
k_x=m_x;
k_y=m_y;
goto al_3;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y+y] == 'k') // Moving Down
{
k_x=m_x;
k_y=m_y;
goto al_4;
}
}
}
al_1:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x-x][m_y] == '*') // Checking left
{
goto loop_exit;
}
}
}
al_2:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x+x][m_y] == '*') // Checking Right
{
goto loop_exit;
}
}
}
al_3:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y-y] == '*') // Checking Up
{
goto loop_exit;
}
}
}
al_4:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y+y] == '*') // Checking Down
{
goto loop_exit;
}
}
}
loop_exit:
check = false;
if (check == true)
{
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
}
}
该函数在 x 和 y 轴上搜索国王在哪里。然后它进入特定算法(al_1、al_2、...),在该算法中搜索国王和车之间是否有任何东西。
输入文件大致如下:
********
***k****
********
***q****
********
********
***R****
********
这不应该什么都不输出,而
********
***k****
********
********
********
********
***R****
********
应该输出"Black is in check by rook "。 (t_i 是正在检查的板的编号)
A[t_i]是一个struct数组,struct块由char field[8][8]组成。
我使用结构体是因为我要检查的板子数量不受限制。
k_x和k_y是王坐标。 m_x 和 m_y 是全局变量,从找到一个片段的搜索功能中传递过来
这是带有 int main()
的程序本身#include <iostream>
#include <fstream> // chess
#include <cstdlib>
using namespace std; // PROGRAM CHECKS FOR CHESS CHEKS
const char FVD[]="5_input.txt"; // **************************************************
const char FVR[]="5_output.txt"; // P - white pawn (WP) p - black pawn (BP)
//--- // R - white rook (WR) r - black rook (BR)
//--- // B - white bishop (WB) b - black bishop (BB)
int m_i=0; // max i // N - white knight (WN) n - black knight (BN)
int m_x=0; // // Q - white queen (WQ) q - black queen (BQ)
int m_y=0; // // K - white king (WK) k - black king (BK)
int t_i=0; // // **************************************************
struct piece
{
char field[8][8];
};
void read(piece A[])
{
ifstream fd(FVD);
int i=0;
m_i=0;
while(!fd.eof())
{
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
fd >> A[i].field[x][y];
}
}
fd.ignore();
i++;
m_i=i;
}
fd.close();
}
/// ----------------------------------------------BLACK KING IS IN CHECK--------------------------------------------------------------
void rook_white(piece A[]) // does WR check BK
{
cout << "Found White Rook ";
int k_x; // BK'S x coordinate
int k_y; // BK's y coordinate
bool check = false;
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x-x][m_y] == 'k') // Moving Left
{
k_x=m_x;
k_y=m_y;
goto al_1;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x+x][m_y] == 'k') // Moving Right
{
k_x=m_x;
k_y=m_y;
goto al_2;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y-y] == 'k') // Moving Up
{
k_x=m_x;
k_y=m_y;
goto al_3;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y+y] == 'k') // Moving Down
{
k_x=m_x;
k_y=m_y;
goto al_4;
}
}
}
al_1:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x-x][m_y] == '*') // Checking left
{
goto loop_exit;
}
}
}
al_2:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x+x][m_y] == '*') // Checking Right
{
goto loop_exit;
}
}
}
al_3:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y-y] == '*') // Checking Up
{
goto loop_exit;
}
}
}
al_4:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y+y] == '*') // Checking Down
{
goto loop_exit;
}
}
}
loop_exit:
check = false;
if (check == true)
{
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
}
}
///-----------------------------------------SEARCHING FOR THE CHECKS // CALLING FUNCTIONS --------------------------------------------
void search(piece A[]) // searches for piece and calls a function related to it
{
for(int i=0; i<m_i-1; i++)
{
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if (A[i].field[x][y]=='R')
{
t_i=i;
m_x=x;
m_y=y;
rook_white(A);
}
}
}
}
}
int main()
{
piece A[10];
remove(FVR); // clears the output before inputting new data because of ios::app
read(A);
search(A);
ofstream fr(FVR);
fr << "Done";
return 0;
}
我会做我平时不做的事情 -- 我会给你一个完整的往返(因为我喜欢)。
你从一个 main()
开始,它应该读取任意数量的字段(但实际上在 11 日崩溃),以及一个 search()
函数,它旨在最终遍历所有可能的棋子...但是您的程序在检查第一块白车时失败了。
您也从 C 开始,然后顺势引入 C++,实际上让事情变得比必要的更困难。
所以让我们trim记下来。 首先,我们会将 "minimal" 放入您的示例代码中。
让我们用<vector>
代替二维数组。向量是 C++ 中 最有用的东西之一,几乎没有理由再使用 C 风格的数组(除了 C API 兼容性)。 =64=]
#include <vector>
#include <iostream>
typedef std::vector< std::vector< char > > Field;
Field
现在是 char
向量的向量的别名。这与二维数组(包括 [][]
寻址)基本相同,但它有一些您很快就会看到的优点。
您的 rook_white()
(如您设计的那样)需要 一个 字段,以及车的 X 和 Y 坐标。请允许我稍微调整一下您的函数原型——我喜欢更具表现力的标识符名称。
void rook_white( Field const & field, unsigned rook_x, unsigned rook_y );
搜索并删除 A[t_i].
,我们现在只处理那个字段。将 m_x
搜索并替换为 rook_x
,将 m_y
替换为 rook_y
。不是太难。同时替换:
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
有:
std::cout << "Black is in check by rook" endl;
现在我们不用理会文件 I/O.
现在,我们需要设置一个字段,但是我们暂时不需要从文件中读取它。实际检查工作后,您可以扩展代码。
int main()
{
Field field( 8, std::vector< char >( 8, '*' ) );
std::vector< char >( 8, '*' )
创建一个 8 '8'
个字符的临时向量。 Field field( 8, /*...*/ );
创建一个 Field
,其中包含该临时向量的 8 个副本。
现在让我们放置你的棋子。
unsigned rook_x = 3;
unsigned rook_y = 6;
field[rook_x][rook_y] = 'R';
unsigned king_x = 3;
unsigned king_y = 1;
field[king_x][king_y] = 'k';
此时我意识到 你的示例代码在 search()
中混淆了 "X" 和 "Y" 坐标(报告 X 处的车= 6,Y = 3),但没关系。那不是你问题的根源。
我们现在有了字段和坐标来调用您的函数。
rook_white( field, rook_x, rook_y );
return 0;
}
这种编写 main()
的方式并没有真正反映您的最终应用程序应该做什么,而是为特定功能设置测试,称为 测试驱动程序。我们刚刚从您的示例中删除了 50 多行不必要的代码,消除了各种不相关的潜在问题。
现在,让我们看看 rook_white()
,好吗?
因为我们现在有一个 vector< vector< char > >
而不是 "dumb" 数组,我们可以做一些漂亮的事情:用 .at()
替换 []
访问。原因?如果 []
的索引越界,它可能会也可能不会使程序崩溃。如果 .at()
的索引越界,它 将 抛出异常。
所以,虽然 .at()
(有点)慢并且通常不在生产代码中使用,但我建议初学者使用它,因为它不允许 "hide".[=64= 的错误]
此时你应该眉头一挑,心想,"why is he suggesting this?"。然后你应该看看你的循环,并且...
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(field[rook_x-x][rook_y] == 'k')
{
k_x=rook_x;
k_y=rook_y;
goto al_1;
}
}
}
是的,没错。您对您的字段有 越界访问 。
rook_x
/ rook_y
在场地中间的某个地方,但如果找不到国王,您坚持访问 [rook_x - 7][rook_y]
之前的任何内容。那是您原始代码中的负索引。由于我将坐标更改为 unsigned
(它会溢出并变得 非常大 ),你会遇到段错误崩溃(如果幸运的话)。那实际上是无意的;我只是声明不能为负的东西 unsigned
by habbit.
但这就是为什么我建议您在学习期间使用 vector<>
的 .at()
方法:尽早失败并尽可能大声地失败。 异常优于未定义的行为。
此外,你(在所有这些循环中)总是循环x
和y
,但只使用 循环中 两个变量中的一个。这是很多 浪费的时钟周期 。这不会破坏您的逻辑只是偶然...
此时您可能想要完全重新编写代码。但是等等,还有更多。
如果您 "move left" 在您的第一个循环中找到国王,那么您 goto al_1
。在那里你循环(再次使用两个循环计数器之一)来检查中间部分。
第一个循环是 x == 0
,检查 [rook_x - 0][rook_y]
... 猜猜看,你发现白车正在介入,因为那里在该字段中没有 '*'
,因此您跳转到 loop_exit
...
即使你没有犯那个错误,你也会从那个循环中出来并输入 al_2
,同时检查车的所有剩余方向...
即使这一切都不会发生,无论发生什么,你最终运行会变成这样:
loop_exit:
check = false;
if (check == true)
{
std::cout << "Black is in check by rook \n";
}
嗯,check == true
永远不会发生,对吧?
在这一点上我引用你的评论之一...
...I just don't understand [switch statements] and couldn't really wrap my head around on how to write them as switch.
我的建议?我完全理解你为什么要尽快写 "something real" 。教科书很无聊。但是你真的应该多花一些时间"wrapping your head around"基本概念。 C 和 C++ 是使用 "trial & error" 方法 学习它们的语言。有太多的事情可以而且将会出错。
We have a list of recommended textbooks, if the one you have isn't to your tastes.
如果你在真正掌握正确的基础知识之前尝试了太多的东西(比如国际象棋程序),那么你可能遇到的任何问题的答案最终都会比舒适的时间长很多,无论是写(如果有人喜欢它)并让你消化。
请:
不要使用 goto
除非你绝对肯定地知道你在做什么。