我正在尝试编写一个功能,检查黑色国王是否被白车检查。当我试图搜索车和国王之间是否有任何碎片时,就会出现问题。
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 in rook”。 (t_i是正在检查的董事会的编号)
A [t_i]是一个struct数组,struct pieces由char字段[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;
}
答案 0 :(得分:4)
我会做我不常做的事情 - 我会给你一个完整的往返行程(因为我觉得这样)。
你开始使用的main()
应该读取任意数量的字段(但实际上是11日崩溃),以及search()
函数,它最终会遍历所有可能的棋子。但是你的程序在检查第一件白色车时失败了。
你也从C开始,然后介绍顺势疗法剂量的C ++,实际上使事情变得更加困难。
所以让我们减少它。 首先,我们将获得&#34; minimal&#34;进入示例代码。
让我们使用<vector>
而不是二维数组。向量是 在C ++中最有用的东西之一,并且几乎没有理由再使用C风格的数组(除了C API兼容性之外)。
#include <vector>
#include <iostream>
typedef std::vector< std::vector< char > > Field;
Field
现在是char
s向量向量的别名。这与二维数组(包括[][]
寻址)基本相同,但它很快就会有一些优势。
您的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';
此时我意识到你的示例代码得到了&#34; X&#34;和&#34; Y&#34;坐标在search()
中混淆(在X = 6,Y = 3时报告车辆),但没关系。这不是你问题的根源。
我们现在有字段和坐标来调用你的函数。
rook_white( field, rook_x, rook_y );
return 0;
}
这种编写main()
并不能真正反映最终应用程序应该执行的操作的方式,而是针对特定功能设置测试,称为测试驱动程序。我们只是从你的例子中删除了50多行不必要的代码,消除了各种不相关的潜在问题。
现在,让我们看一下rook_white()
,不管吗?
因为我们现在有vector< vector< char > >
而不是&#34; dumb&#34;数组,我们可以做一些漂亮的事情:用[]
替换.at()
访问权限。原因?如果[]
的索引超出范围,则可能会也可能不会使程序崩溃。如果.at()
的索引超出范围,将抛出异常。
所以,虽然.at()
有点慢(通常不会在生产代码中使用),但我建议初学者使用它,因为它不允许错误&#34;隐藏&#34;。
此时你应该挑起眉毛,自己思考,&#34;他为什么要这样做?&#34;。然后你应该看看你的循环,然后......
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
(相反溢出并变为非常大),您将遇到段错误(如果您很幸运)。那实际上是无意的;我只是通过habbit宣布不能为负unsigned
的内容。
但这就是为什么我建议在您还在学习的同时使用vector<>
的{{1}}方法:尽可能早地和尽可能地失败。 异常优于未定义的行为。
此外,您(在所有这些循环中)始终循环遍历.at()
和 x
,但仅使用 one < / em>中的两个变量在循环中。这有很多浪费的时钟周期。这不会打破你的逻辑只是机会...
此时您可能希望完全重新编写代码。但等等,还有更多。
如果你&#34;向左移动&#34;在你的第一个循环中,找到那里的王,你y
。在那里你循环(再次使用两个循环计数器中的一个)来检查干预部分。
第一个循环是goto al_1
,检查x == 0
......好好猜测,你发现白车要介入,因为没有{{1在该字段中,您跳转到[rook_x - 0][rook_y]
...
即使你不会犯这个错误,你也会走出那个循环并进入'*'
,同时检查所有剩余的方向。
即使一切都不会发生,无论发生什么,你最终都会碰到这个:
loop_exit
嗯, al_2
永远不会发生,对吗?
此时我引用你的一条评论......
......我只是不理解[转换语句]并且无法真正理解如何将它们写为开关。
我的建议?我完全理解你为什么要写一些真实的东西&#34;尽可能快地。教科书很无聊。但你真的应该花更多的时间和#34;包裹你的头脑#34;基本概念。 C和C ++是一种非常适用于&#34;试用版和C&C的语言。错误&#34;接近来学习它们。有太多可能,而且会出错。
We have a list of recommended textbooks, if the one you have isn't to your tastes.
如果你在真正掌握了基本知识之前尝试了太大的东西(比如国际象棋程序),你可能会遇到的任何问题的答案最终会比舒适的时间长得多,无论是写作(如果有人感觉到的话)喜欢它,并为你消化。
请:
不要使用loop_exit:
check = false;
if (check == true)
{
std::cout << "Black is in check by rook \n";
}
,除非你绝对,积极地知道自己在做什么。