从0开始写中国象棋 您所在的位置:网站首页 象棋每走一步的叫法 从0开始写中国象棋

从0开始写中国象棋

2024-07-17 07:35| 来源: 网络整理| 查看: 265

在文章 从0开始写中国象棋-创建棋盘与棋子

中,我们已经可以看到象棋游戏的界面了。

这是因为,我们创建了棋盘(棋盘数组),并在棋盘上放置一些数字来表示棋子。

让棋子动起来

现在,我们打算让棋子动起来。

棋子动起来,其实很简单,比如开局 炮二平五。

实际上就是棋子从棋盘上的一个位置移动到了棋盘的另一个位置。

实际上是棋盘在变化

对应棋盘的变化就是,棋盘从:

变成了:

由于棋盘上的棋子就是一个一个的不同的数字,所以,从计算机的角度来说,走一步棋就是给二维数组的一个位置设置一个新数字。

也就是,起点位置元素重新赋值为0(表示这里没有棋子了,棋子走到其他位置去了);

终点位置元素重新赋值为炮的ID(表示炮走棋来到了这里)。

程序实现 GoAhead(OneStep)

现在我们希望告诉程序,走一步棋,从一个位置走到另一个位置,程序就能够实现这个目标。

由于这种需求是在下棋双方走棋的时候反复出现的,所以我们可以很方便的用函数来实现。

这个函数大概像下面这样:

bool GoAhead(from_row, from_col, to_row, to_col);

其中,各个参数的意思是很明显的,我们就不解释了。

但是,函数返回值是bool,这个是干什么的呢?

因为用户可能会乱走棋,比如,蹩马腿了也要跳马,这个时候你就要告诉他不能走这步棋。这时候函数返回 false 。

现在让我们来实现这个函数:

bool GoAhead(int from_row, int from_col, int to_row, int to_col) { //如果出发的地方没有旗子,就返回 false if() }

这个时候我们才发现我们需要访问棋盘。

而棋盘是定义在main函数内的变量。我们访问不到。

怎么办?

C++全局变量

不在函数内定义的变量就叫全局变量。

为了能够让任何代码都访问到棋盘,我们在程序的一开始就定义棋盘。这样我们的函数就可以访问棋盘了。

//棋盘数组,不同的数字表示不同的棋子,0表示没有棋子 vector chess_board { { 1, 2, 3, 4, 5, 6, 7, 8, 9}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0,10, 0, 0, 0, 0, 0,11, 0}, {12, 0,13, 0,14, 0,15, 0,16}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, {26, 0,27, 0,28, 0,29, 0,30}, { 0,31, 0, 0, 0, 0, 0,32, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, {17,18,19,20,21,22,23,24,25}, }; bool GoAhead(int from_row, int from_col, int to_row, int to_col) { //如果出发的地方没有旗子,就返回 false if (chess_board[from_row][from_col] != 0) { } else { return false; } } 谁能告诉我能否走到哪里?

现在的问题是,当走棋的起点有棋子的时候,这个棋子能否到达目的地位置?

也就是走棋的合理性问题。

这里门道就多了:马走日,相走田,车走直路,炮翻山,小卒一去不会还。

如何实现这样的需求呢?

C++的方式是使用多态来实现。伪代码像下面这样:

//棋子类的基类 struct chess_base { // 纯虚函数,表示 chess_base 是一个抽象类,专门用来做基类; //GoAhead 用来给各个派生类来重新实现 override virtual bool GoAhead(int from_row, int from_col, int to_row, int to_col) = 0; }; struct Horse : public chess_base { // 马实现自己的走棋 bool GoAhead(int from_row, int from_col, int to_row, int to_col) { //ba la ba la .... return false; } }; struct King : public chess_base { // 帅实现自己的走棋 bool GoAhead(int from_row, int from_col, int to_row, int to_col) { //ba la ba la .... return false; } };

每个棋子都知道自己的规则,所以自己是知道能否走到目的地的。

这也就要求我们要替各个棋子来实现它们各自的走法。

棋子数组包含对象

之前,我们的棋子数组是不同位置(数组下标)表示不同棋子,棋子只有一个内容,就是它们的名字。

现在,我们希望用类对象来表示。名字只是棋子的一个成员变量。走棋GoAhead才是棋子的主要能力。

#include #include #include #include using namespace std; //棋盘数组,不同的数字表示不同的棋子,0表示没有棋子 vector chess_board { { 1, 2, 3, 4, 5, 6, 7, 8, 9}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0,10, 0, 0, 0, 0, 0,11, 0}, {12, 0,13, 0,14, 0,15, 0,16}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, {26, 0,27, 0,28, 0,29, 0,30}, { 0,31, 0, 0, 0, 0, 0,32, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0}, {17,18,19,20,21,22,23,24,25}, }; //棋子类的基类 struct chess_base { chess_base(const string& name1):name(name1){} // 纯虚函数,表示 chess_base 是一个抽象类,专门用来做基类; //GoAhead 用来给各个派生类来重新实现 override virtual bool GoAhead(int from_row, int from_col, int to_row, int to_col) = 0; string name;//棋子要显示的名字 }; //车 車 struct Chariot : public chess_base { Chariot(const string& name1) :chess_base(name1) {} // 马实现自己的走棋 bool GoAhead(int from_row, int from_col, int to_row, int to_col) { cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有