C++中国象棋

ssdut c++的大作业,在控制台的界面实现人人对弈,比较适合初学,自己设计了一些简单算法,两百多行完成。

以下正文:

完成中国象棋游戏,实现如下功能:

1.实现人与人之间象棋的对弈。

2.每次走子之前都会判断是否符合规则,若不符合规则就要重新走子。

3.程序随时判断是否有一方取得胜利,该局结束。

类的设计:

1.chess:棋子类,有int型私有变量id存储棋子的编号。作为基类派生出其他具体的棋子类。有判断棋子走法是否符合规则的judge_move()纯虚函数。

代码:

class chess{
private:int id;//等级
public:chess(int i):id(i){}int get(){return id;}virtual bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy)=0;virtual ~chess(){};//虚析构
};

2.具体的棋子类:包括soldier类、horse类、rook类、guard类、cannon类、elephant类、general类分别代表兵(卒)、馬(马)、車(车)、士(仕)、炮(砲)、相(象)、帅(将)的类,由chess类作为基类派生。每个派生类都对judge_move()函数进行重写。

以马为例:

class horse : public chess{//马的实现
public:horse(int i) : chess((i==0?-2:2)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&(tempx*tempx+tempy*tempy==5)&&!cb.get(startx+tempx/2,starty+tempy/2))return true;return false;}
};

3.chessboard类:棋盘类,私有成员包括10*9的指向chess的指针数组用以存储各个棋子对象的地址,并通过指针调用实现多态。

代码:

class chessboard{
private:chess *c[10][9];//用指针调用各个棋子,实现多态char chessword[15][4]={"帅","相","炮","士","車","馬","兵","","卒","马","车","仕","砲","象","将"};//名字
public:chessboard(){memset(c, NULL, sizeof(c));};//把指针初始化为零指针void init();chess* get(int x,int y){return c[x][y];}int getid(int x,int y){ if(c[x][y]!=NULL) return c[x][y]->get();return 0;}void show();void play();bool move(int startx,int starty,int aimx,int aimy);~chessboard();//析构函数static bool end;//判断结束static int player;
};

算法描述:

红方棋子中文分别为"兵","馬","車","士","炮","相","帅"。

id的编号分别为-1、-2、-3、-4、-5、-6、-7。

黑方棋子:中文分别为"卒","马","车","仕","砲","象","将"。

id的编号分别为1、2、3、4、5、6、7。

(由于只显示一个汉子表示棋子,所以用“砲”作为红方的炮)

维护的变量:

startx starty: 开始的位置 ;  aimx  aimy:目标的位置

sid:存储开始位置的棋子的编号,若该点没有棋子(空指针),则值为0。

aid:存储目标位置的棋子的编号,若该点没有棋子(空指针),则值为0。

tempx:开始位置到目标位置的x坐标的偏移量(aimx-startx)。

 

tempy:开始位置到目标位置的y坐标的偏移量(aimy-starty)。

 

 

走棋的实现:

 

每次把位置信息传到chessboard类的move()函数时,会判断:

1.传入的两个位置是否越界(超出了10*9数组的范围),越界则返回false

2.传入的开始位置的点的id是否为零(当点上无棋子,也就是空指针的时候为零),若为零则返回false。

3.当前选的棋子是否是这一回对应那一方的棋子,若不是则返回false

4.对当前棋子的具体规则进行判断(通过指针调用虚函数,判断该棋子的具体规则,多态的实现)。若错误则返回false

若以上判断都准确无误,则把棋子走到对应位置:

1.不吃子:目标位置为空指针时,把目标位置的指针指向该棋子对象,把棋子的起始位置指针赋值NULL,设为空指针。

2. 吃子:delete目标位置的棋子对象,该棋子被吃。把目标位置的指针指向该棋子对象,把棋子的起始位置指针赋值NULL,设为空指针。

判断结束:

 

棋盘类有一个静态变量bool end, 初始化为true。当将(帅)对象被析构时,把end赋值为false,表示棋局结束,退出走棋的循环(while(chessboard :: end)控制走棋是否继续)。

输出胜利的一方的信息:

棋盘类有一个静态变量int player,初始化为-1,每走棋一次乘以-1,在1-1之间交替表示棋手的轮流下棋。以此来鉴别胜利的是哪一方。

 

棋子具体的规则算法:

1.判断目标点是否是己方的棋:两方的子的id互为相反数,所以只有当sid*aid>0时表示目标位置是己方的子,不能走。因而只有满足sid*aid<=0才是合法条件(空位置为0)。

2.判断是否满足只能走1格,或马走日,象走田的条件时,只需要区偏移的距离进行判断。例如temp*temp+tempy+tempy表示偏移量的平方,当该值为1时,表示只走了任意方向的一格;当值为2时,表示士的斜走;值为5时,表示马走日;为8时,表示象走田。

3.判断马走日的蹩脚马时,用数学计算方法,可以归纳出只需判断(x+tempx/2,y+tempy/2)位置是否有子便可。而判断塞象时,只用判段(x+tempx/2,y+tempy/2)的位置是否有子即可。

4.判断将(帅)和士是否在3*3的营里:明显,y坐标肯定要满足y>=3&&y<=5,而x坐标只需对7取模,就可以把0-27-9约束在0-2里,判断即可:aimx%7>=0&&aimx%7<=2。

其他一些规则如兵不能回头(sid*tempx<=0),过河后可以横走,炮只能隔子吃子,已经在代码实现,不详述。

输出如下:

 

1.棋盘的构建,输入的界面:

 

2.按规则正确输入后的界面:

3.不按规则,错误输入的界面:

4.某一方将(帅)被吃,结束的界面:

附上完整代码:

#include <iostream>
#include <memory.h>
#include <math.h>
using namespace std;//存储结构:chess类是基类,派生类是各种棋子,在chessboard类中用chess的指针调用各个棋子
class chessboard;
class chess{
private:int id;//等级
public:chess(int i):id(i){}int get(){return id;}virtual bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy)=0;virtual ~chess(){};//虚析构
};class chessboard{
private:chess *c[10][9];//用指针调用各个棋子,实现多态char chessword[15][4]={"帅","相","炮","士","車","馬","兵","","卒","马","车","仕","砲","象","将"};//名字
public:chessboard(){memset(c, NULL, sizeof(c));};//把指针初始化为零指针void init();chess* get(int x,int y){return c[x][y];}int getid(int x,int y){ if(c[x][y]!=NULL) return c[x][y]->get();return 0;}void show();void play();bool move(int startx,int starty,int aimx,int aimy);~chessboard();//析构函数static bool end;//判断结束static int player;
};bool chessboard::end=true;
int chessboard::player=-1;bool chessboard::move(int startx,int starty,int aimx,int aimy){if(startx>=0&&startx<10&&starty>=0&&starty<9//初步判断传入的点是否符合规则&&aimx>=0&&aimx<10&&aimy>=0&&aimy<9&&getid(startx,starty)&&getid(startx,starty)*player>0&&c[startx][starty]->judge_move(*this,startx,starty,aimx,aimy)){if(c[aimx][aimy]!=NULL) delete c[aimx][aimy];//吃子c[aimx][aimy]=c[startx][starty];c[startx][starty]=NULL;player*=-1;return true;}cout<<"走法错误,不符合规则"<<endl;return false;
}class horse : public chess{//马的实现
public:horse(int i) : chess((i==0?-2:2)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&(tempx*tempx+tempy*tempy==5)&&!cb.get(startx+tempx/2,starty+tempy/2))return true;return false;}
};class soldier : public chess{//兵(卒)的实现
public:soldier(int c) : chess((c==0?-1:1)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&sid*tempx<=0){if(abs(tempx)==1&&tempy==0) return true;if(abs(tempy)==1&&tempx==0)if((startx/5==0&&sid>0)||(startx/5==1&&sid<0)) return true;return false;}return false;}
};class general : public chess{//帅(将)的实现
public:general(int c) : chess((c==0?-7:7)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&tempy*tempy+tempx*tempx==1&&aimx%7>=0&&aimx%7<=2&&aimy>=3&&aimy<=5)return true;return false;}~general(){chessboard::end=false;}
};class elephant : public chess{//象(相)的实现
public:elephant(int c) : chess((c==0?-6:6)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&tempy*tempy+tempx*tempx==8&&startx/5==aimx/5&&!cb.get(startx+tempx/2,starty+tempy/2))return true;return false;}
};class cannon : public chess{//炮的实现
public:cannon(int c) : chess((c==0?-5:5)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&!(tempx&&tempy)&&(tempx+tempy)){int tot=0;if(tempx!=0){int sign=tempx>0?1:-1;for(int i=1;i<abs(tempx);i++)if(cb.get(startx+sign*i,starty)) tot++;}else{int sign=tempy>0?1:-1;for(int i=1;i<abs(tempy);i++)if(cb.get(startx,starty+sign*i)) tot++;}if(!aid){if(!tot) return true;}else{if(tot==1) return true;}}return false;}
};class guard: public chess{//士(仕)的实现
public:guard(int c) : chess((c==0?-4:4)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&tempy*tempy+tempx*tempx==2&&aimx%7>=0&&aimx%7<=2&&aimy>=3&&aimy<=5)return true;return false;}
};class rook : public chess{//车的实现
public:rook(int c) : chess((c==0?-3:3)){}bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){int tempx=aimx-startx,tempy=aimy-starty;int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);if(sid*aid<=0&&!(tempx&&tempy)&&(tempx+tempy)){if(tempx!=0){int sign=tempx>0?1:-1;for(int i=1;i<abs(tempx);i++)if(cb.get(startx+sign*i,starty)) return false;}else{int sign=tempy>0?1:-1;for(int i=1;i<abs(tempy);i++)if(cb.get(startx,starty+sign*i)) return false;}return true;}return false;}
};chessboard :: ~chessboard(){for(int i=0;i<10;i++)for(int j=0;j<9;j++)if(c[i][j]!=NULL){delete c[i][j];c[i][j]=NULL;}
}void chessboard :: init(){//初始化,棋子的生成c[0][0]=new rook(0);        c[0][8]=new rook(0);c[0][1]=new horse(0);       c[0][7]=new horse(0);c[0][2]=new elephant(0);    c[0][6]=new elephant(0);c[0][3]=new guard(0);       c[0][5]=new guard(0);c[0][4]=new general(0);     c[9][4]=new general(1);c[2][1]=new cannon(0);      c[2][7]=new cannon(0);c[3][0]=new soldier(0);     c[3][2]=new soldier(0);c[3][4]=new soldier(0);     c[3][6]=new soldier(0);c[3][8]=new soldier(0);     c[6][8]=new soldier(1);c[6][0]=new soldier(1);     c[6][2]=new soldier(1);c[6][4]=new soldier(1);     c[6][6]=new soldier(1);c[7][1]=new cannon(1);      c[7][7]=new cannon(1);c[9][0]=new rook(1);        c[9][8]=new rook(1);c[9][1]=new horse(1);       c[9][7]=new horse(1);c[9][2]=new elephant(1);    c[9][6]=new elephant(1);c[9][3]=new guard(1);       c[9][5]=new guard(1);
}void chessboard :: show(){cout<<"吴  零一二三四五六七八"<<endl<<endl;char num[10][4]={"零","一","二","三","四","五","六","七","八","九"};for(int i=0;i<10;i++){if(i==5) cout<<"    ——楚 河 汉 界———"<<endl;cout<<num[i]<<"  ";for(int j=0;j<9;j++){if(c[i][j]!=NULL)cout<<chessword[c[i][j]->get()+7];else if((i==1&&j==4)||(i==8&&j==4))cout<<"米";elsecout<<"十";}cout<<endl;}
}void chessboard::play(){this->init();this->show();do{int startx,starty,aimx,aimy;int sid,aid;do{sid=aid=0;cout<<"请输入起始棋子位置与目标位置的坐标:"<<endl;cin>>startx>>starty>>aimx>>aimy;}while(!this->move(startx,starty,aimx,aimy));this->show();}while(chessboard::end);cout<<"结束,赢家是Player"<<(chessboard::player==1?1:2)<<endl;
}int main(){chessboard C;C.play();
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/58686.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java版本实现中国象棋

预览效果 中国象棋 游戏介绍&#xff1a;中国象棋是起源于中国的一种棋&#xff0c;属于二人对抗性游戏的一种&#xff0c;在中国有着悠久的历史&#xff0c;由于用具简单&#xff0c;趣味性强&#xff0c;成为流行极为广泛的棋艺活动。阿巴阿巴阿巴 代码结构&#xff1a;Butto…

数影周报:小米汽车供应商被罚100万,1688延迟下线“1688买家旺旺”

本周看点&#xff1a;小米汽车供应商被罚100万&#xff1b;特斯拉将在硅谷招聘AI 人才&#xff1b;阳光出行等25款 App涉违规收集使用个人信息等&#xff1b;1688延迟于2月8日下线“1688买家旺旺”&#xff1b;微蚁科技完成数千万元B轮融资...... 数据安全那些事 小米汽车供应商…

Coggle 30 Days of ML (23年7月)任务二:数据可视化

Coggle 30 Days of ML (23年7月&#xff09;任务二&#xff1a;数据可视化 任务二&#xff1a;对数据集字符进行可视化&#xff0c;统计标签和字符分布 说明&#xff1a;在这个任务中&#xff0c;需要使用Pandas库对数据集的字符进行可视化&#xff0c;并统计数据集中的标签和…

阿里云服务器ECS是什么?详细介绍

阿里云服务器ECS是什么&#xff1f;云服务器和传统的物理服务器有什么区别&#xff1f;云服务器有哪些优势&#xff1f;云服务器可以什么&#xff1f;云服务器架构及云服务器包含哪些功能组件&#xff1f;阿里云百科来详细说下什么是云服务器ECS&#xff1a; 目录 阿里云服务…

使用Chrome修改user agent模拟微信内置浏览器

很多时候&#xff0c;我们需要模拟微信内置浏览器&#xff0c;今天教大家用 chrome 简单模拟。如图设置&#xff1a; F12或者右键审查元素进入开发者模式&#xff0c;点击Emulation&#xff0c;然后点击Network&#xff0c;把Spoof user agent改成Other&#xff0c;并把下面…

数据分析案例-足球运动员分析

目录 加载数据 查看数据 数据详细 ​缺值处理 异常值处理 重复值处理 运动员身高和体重分布 左脚右脚使用数量 俱乐部球员评分分析 足球运动员数是否与出生日期相关 身高与体重是否具有相关性 加载数据 #加载足球运动员数据 import numpy as np import pandas as pd impor…

如何用算法预测世界杯?

预测2021欧洲世界杯 世界杯预测结果预测的原理是什么&#xff1f;周易算卦原理算命可以解决的问题善易者不卜 人工智能预测原理预测模型&#xff1a;逻辑回归算法可以预测的问题 可以单挑整个华尔街的算法现代足球 世界杯预测结果 预测2021年欧洲世界杯&#xff0c;也是一道考…

采用 Python 机器学习预测足球比赛结果

足球是世界上最火爆的运动之一,如何运用机器学习来预测足球比赛结果,是每一个足球爱好者所向往的! 本场 Chat 适合有 Python 基础的机器学习初学者,我们带你一起熟悉机器学习的开发流程,帮你快速建立起自己的英超比赛预测模型! 你将获取到如下内容: 人工智能在线建模平…

按键精灵移动端系列 - 按键精灵IOS版 之 网络已断开,请检查网络连接.解决方案.

由于很多网友对这种问题,不知道如何处理.因本人也曾遇到过这种情况.经过不懈努力终于解决了这个神奇的BUG.长话短说上操作流程.如果觉得给力,请三连 点赞. 收藏. 转发. 谢谢您的支持. ** 1 安装雷锋源: apt.abcydia.com 2安装好雷锋源, 搜索: conditionalwifi 更新到最新版 …

按键精灵助手无法连接模拟器解决方案【适用任何模拟器】

找到按键精灵安装地址 D:\ProgramData\按键精灵\按键精灵手机助手\android 找到木木安装地址&#xff0c;并搜索adb.exe,未找到 但是在D:\Program Files (x86)\MuMu\emulator\nemu\vmonitor\bin找到 adb_server.exe 以及另外两个.dll 复制着三个文件到按键精灵上述文件夹&#…

国行版苹果 ios 按键精灵无法联网问题处理

国行版苹果手机安装按键精灵后无法联网的问题&#xff1a; 操作步骤&#xff1a; &#xff08;1&#xff09;自行把苹果手机进行越狱&#xff0c;找到并打开越狱商店“Cydia” &#xff0c;其他商店同理&#xff0c;按照如下图步骤添加 “雷锋源”&#xff0c;源地址&#xff…

网易mumu显示无法连接服务器,网易MuMu无法连接网络_网易MuMu如何实现多开

网易MuMu是由网易全方面打造的一种非常具有精品特色的游戏服务平台&#xff0c;这款游戏服务平台在下载安装之后可以直接运行电脑上的各种不同游戏和应用程序&#xff0c;同时它的兼容性是比较强的&#xff0c;有着非常流畅的操作过程&#xff0c;还可以通过智能辅助等优秀特色…

网易mumu模拟器adb连接配置

一、 网易mumu模拟器下载 二、安装模拟器到本机指定目录 1、例如&#xff1a;D:\Program Files\MuMu 2、adb文配置相关文件位于&#xff1a;D:\Program Files\MuMu\emulator\nemu\vms\myandrovm_vbox86下&#xff0c;如下图所示&#xff1a; 3、打开myandrovm_vbox86.nemu文件…

uni-app 连接不上夜神模拟器

uni-app 连接不上夜神模拟器 第一步打开运行设置 设置端口号 第二步通过cmd命令去连接模拟器 我这利用的是HX 找到&#xff1a;HBuilderX.3.1.17.20210608.full\HBuilderX\plugins\launcher\tools\adbs 直接cmd 执行下面两个命令 adb connect 127.0.0.1:62001 adb devices…

夜神模拟器无法连接网络的解决办法

我们经常会在电脑上安装安卓模拟器来玩一些手机游戏或者运行手机软件&#xff0c;但是有时候可能由于网络不好等原因导致模拟器连接不上网络。比如夜神模拟器无法连接网络怎么办&#xff1f;下面就来看看解决的办法。 夜神模拟器无法连接网络怎么办&#xff1a; 1、同时按下“w…

按键精灵手机助手如何连接安卓版按键精灵如何连接手机助手

通过上述讲解过的按键精灵如何下载文章得知,按键精灵手机版分为两个版本,分别为安卓版和IOS版,都是需要连接在按键精灵手机助手运行,按键精灵手机助手则必须在电脑上安装运行。好的,下面我们就来逐步讲解一下,手机版按键精灵如何使用。 首先,我们打开已经安装完成的按键…

天天模拟器显示获取服务器失败,天天模拟器无法联网怎么办-天天模拟器不能上网的解决方法 - 河东软件园...

天天模拟器是目前最热门的安卓模拟器软件&#xff0c;这是国内自主研发的一款优秀模拟器&#xff0c;其采用了持OpenGL硬件加速技术&#xff0c;能够帮助用户稳定的运行各类安卓应用&#xff0c;&#xff0c;并且具备了应用多开&#xff0c;软件具备了操作简单、稳定流畅等诸多…

qq手机助手连接服务器失败是什么原因,按键精灵手机助手教程,按键精灵手机助手连不上手机解决方法...

下面是按键精灵手机助手教程&#xff0c;按键精灵手机助手连不上手机解决方法 一、打开已安装的软件并单击[新建脚本]以创建新的游戏脚本 二、单击[我的脚本]查看创建或下载的脚本 三、点击[移动连接]将您的移动电话与数据线连接&#xff0c;方便测试脚本 我们得到了根用户的许…

总是助手服务器失败怎么回事,《遇见逆水寒》连接服务器失败解决方法汇总 服务器连接失败问题原因...

导 读 遇见逆水寒连接服务器失败怎么回事&#xff0c;近期不少小伙伴都在反映遇见逆水寒助手连接服务器失败&#xff0c;一直登不上去是怎么回事&#xff0c;小编这就为大家分享下遇见逆水寒连接服务器失败解决方法。 遇见逆水寒连接服务器失败解决方法... 遇见逆水寒连接服务器…

遇见逆水寒最新服务器是哪个,遇见逆水寒连接服务器失败怎么回事_遇见逆水寒连接服务器失败解决办法_玩游戏网...

《遇见逆水寒》是《逆水寒》同版本的手游系列&#xff0c;也是拥有了很多的玩家&#xff0c;最近玩家在登录《遇见逆水寒》服务器的时候遇到了连接失败的情况&#xff0c;这是怎么回事呢&#xff1f;要如何解决呢&#xff1f;下面就和玩游网小编一起来了解一下&#xff01; 《遇…