写一个五子棋,主要有三个部分。
1. 界面。
2.下棋功能的实现。
3.人机对战的算法。
1.界面
界面分为两块:菜单,和下棋面板。
菜单要实现基本的功能,开始,撤销,和离开。要实现这些功能就写一个菜单监听器,并且对每一个菜单项setActionCommand,通过判断ActionCommand来分别实现不同的功能。
下棋必须要有格子,这个格子是画了以后就再不会发生改变的,所以把画格子写成一个方法,在重绘时调用就好了。我用的是一个JPanel贴在窗体上,所以就必须在JPanel上得到画布对象,并且实现重绘。
class ChessPanel extends JPanel{
//画格子
public void drawPanel(Graphics g){
//横向十五条线
for (int i = 0; i < Config.Row; i++) {
g.drawLine(Config.X0, Config.Y0 + i * Config.Size, Config.X0
+ (Config.Column - 1) * Config.Size, Config.Size * i
+ Config.Y0);
}
//纵向十五条线
for (int j = 0; j < Config.Column; j++) {
g.drawLine(Config.X0 + j * Config.Size, Config.Y0, Config.X0
+ j * Config.Size, (Config.Row - 1) * Config.Size
+ Config.Y0);
}
}
//重绘棋子
public void drawChess(Graphics g){
for(int i=0;i<chesslist.size();i++){
Qizi qz=chesslist.get(i);
qz.draw(g);
}
}
//重绘窗口
public void paint(Graphics g){
super.paint(g);
drawPanel(g);
drawChess(g);
}
}
这里的config是什么意思呢?就是configuration的意思(配置)。
在所有的代码里,有些东西是会重复使用很多次的。比如列数,行数,棋子大小等等。这些如果直接写(我们把它叫做硬代码),很容易出错,而且很繁琐,一旦要修改就会很麻烦。如果都用一个引用传递的话,全都只需要输入变量名就可以了,实际的值只在Config里面调用,这样需要修改的时候,就只要轻轻改动Config里面的一项或几项就可以了。
2.下棋
和我们自己下棋一样,下棋的步骤为:
找点-->落子
机器也是这样下棋的。我们用一个二维数组来存储棋盘,对棋盘加一个监听器,同时把棋子封装成一个Qizi类,这样对撤销与重绘的实现是有好处的。这个待会再说。
机器没有眼睛不可能一眼看出你下的是哪里,马上给你画上,于是只好很笨很笨的遍历整个二维数组,同时算出哪个位置与你的鼠标落点最接近。
public void mouseReleased(MouseEvent e) {
//鼠标释放时的坐标
int x1=e.getX();
int y1=e.getY();
for(int i=0;i<Config.Row;i++){
for(int j=0;j<Config.Column;j++){
//换算出每一点的坐标,并进行比较
int x=Config.X0+Config.Size*i;
int y=Config.Y0+Config.Size*j;
//误差为格子大小的三分之一
if(Math.abs(x1-x)<Config.Size/3
&&Math.abs(y1-y)<Config.Size/3){
//如果点为空且棋盘可以继续下子
if(UI.chessTable[i][j]==0&&isChange==true){
putChess(i,j,1);//下黑子
}
}
return;
}
}
}
}
注意:1.这里一定要有适当的误差,不然点击的时候很难点准。
2.要把下子写成一个方法,并且可以传参,不论是机器下子还是人下子,都可以调用。这样就会节省很多代码。
下子的方法要包括那些呢?
要可以画一个圆圆的棋子,这个棋子可以指定颜色,同时要把棋子存到重绘的队列里面去。下了棋以后还要判断输赢。
看代码
public void putChess(int r,int c,int flag){
//根据给定的下标算出坐标
int x=Config.X0+r*Config.Size;
int y=Config.Y0+c*Config.Size;
//判定棋子颜色
if(flag==1){
color=Color.BLACK;
}else if(flag==-1){
color=Color.WHITE;
}
//修改棋盘
UI.chessTable[r][c]=flag;
//画棋子
Qizi qz = new Qizi(x,y,color);
qz.draw(g);
//把棋子存入重绘队列
chesslist.add(qz);
//判断输赢
isWin(r,c);
}
判断输赢的方法就是得到下棋的那个点的下标,向四个方向遍历,看是不是有五个子连在一起。只要有一个方向上有五个子连在一起就赢了。
举一个横向的例子
public int checkRow(int r,int c,int[][]chessTable){
int cnt=0;
for(int j=c+1;j<Config.Column;j++){
if(chessTable[r][j]==chessTable[r][c]){
cnt++;
}else
break;
}
for(int j=c;j>=0;j--){
if(chessTable[r][j]==chessTable[r][c]){
cnt++;
}else
break;
}
return cnt;
}
再说说重绘和撤销:
可以看到最上面关于棋盘JPanel的代码,里面有关于重绘的实现,就是把存入队列中的棋子对象一个一个的取出来,重新画上去。
撤销也是一样,首先得到队列的最后一个棋子对象,通过getter和setter方法得到要删除棋子的坐标,这个要写在Qizi的类里面,根据坐标把存有棋盘的二维数组上对应的点清空,然后把队列最后一个棋子对象删除就可以了,注意,删除之后要刷新一下,repaint()
3.人机对战算法
小湖的人机算法很笨,不过对于初学者来说算是最容易理解的方法了。
首先你得有一个机器人类,这个机器人就是与你下棋的对手。机器人有什么功能?就是根据棋盘上的形式选择它自己该下哪个点。
public int[] choosePoint() :这个是找点下子的方法,返回值就是这个点,包括横坐标,纵坐标,以及权值。
int[] point = new int[3];
// 重置权值表
clearValue(Config.Values);
// 给每个点赋权值
for (int i = 0; i < Config.Row; i++) {
for (int j = 0; j < Config.Column; j++) {
if (UI.chessTable[i][j] == 0) {
Config.Values[i][j] = this.setValue(i, j, -1);
}
}
}
// 得到最大权值的点
point = this.getMaxPoint(Config.Values);
return point;
}
把清空权值表和遍历得到最大权值点都写成方法。
public int setValueSimple(int r, int c, int flag,int[][]chesstable):这是给某个点赋基本权值的方法,何谓基本权值?就是目前这个点的棋型能打几分。此时就把几种基本棋型(某一单一方向上)对应的权值一一列举出来。
public int setValue(int r,int c,int flag):这是定最终权值的方法。
由于下棋并不能只看表面,否则就很容易范目光短浅的错误,掉入对手的陷阱里,同时自己的攻势也太直白,对手轻而易举就可以化解,所以除了基本权值之外还要多猜几步,我下这里对方最可能下哪里?对方会不会赢?如果对方会赢那么无论这个权值有多大都不可以下这里了。猜测几步之后,可以用一定的权数进行最终权值的确定。
public int setValue(int r,int c,int flag){
int value=setValueSimple(r,c,flag,UI.chessTable);//定基本权值
clearValue(GuessTable);//清零猜测棋盘
//复制猜测棋盘
for(int i=0;i<Config.Column;i++){
for(int j=0;j<Config.Row;j++){
GuessTable [i][j]=UI.chessTable[i][j];
}
}
point_duifang=guess(r,c,-flag);//假设我下在这里,同时猜对方
if(isWin(r,c)==false){//非我胜点,继续
if(isWin(point_duifang[1],point_duifang[2])==true){
//判断,对方下在这里会赢
value=0;
} else{//否则继续猜下去
point_ziji=guess(point_duifang[1],point_duifang[2],flag);
//对方如果下了,猜自己
value=value*2/3+point_ziji[2]/3;
point_duifang=guess(r,c,-flag);//猜对方
if(isWin(point_duifang[1],point_duifang[2])==true){
//判断,对方下在这里会赢
value=value/4;
}else{//否则继续猜下去
point_ziji=guess(point_duifang[1],point_duifang[2],flag);
//对方如果下了,猜自己
value=value*2/3+point_ziji[2]/3;
point_duifang=guess(r,c,-flag);//猜对方
if(isWin(point_duifang[1],point_duifang[2])==true){
//判断,对方下在这里会赢
value=value/4;
}else{//否则继续猜下去
point_ziji=guess(point_duifang[1],point_duifang[2],flag);
//对方如果下了,猜自己
value=value*2/3+point_ziji[2]/3;
}
}
}
}
return value;
}
这里面猜测了三步,其实可以用迭代的方法,但是由于代码不多我就直接敲上去了。猜测时需要调用猜测的方法,就是传入一个复制了当前棋盘的猜测棋盘二维数组以及要猜测的对象。进行如下步骤
在猜测棋盘上假下子--》遍历找点--》判断权值,存入猜测用权值表(这个表每一次调用都要清零)--》找到权值最大的点,返回。
这种方法很耗时间,如果猜测多于五步就很慢了。
在找点下子的方法中得到最终的权值以后,就可以下子了。之前是在棋盘面板的监听器上手动下子,机器下子也可以添加到那里。只要在人下子的地方多三行代码。
if(isChange==true){
int []point=robot.choosePoint();
putChess(point[1],point[2],-1);
}
isChange指的是棋盘可不可以继续下子。如果有人赢了,isChange就是false ,如果没有人赢isChange就是true。
把机器人类地实例化写在监听器的属性里面,这样就只用实例化一次了,节省了计算机的资源。
其实这个算法很傻,至少连五子棋菜鸟某人都可以做个常胜将军,不过至少让我理解了此类游戏的大致原理。受益颇多。
分享到:
相关推荐
在IT领域,游戏开发是一项非常有趣的实践,尤其是像五子棋这样的经典棋类游戏。"vc#五子棋!!人机对战"项目是利用C#编程语言开发的一个五子棋应用,它允许用户与计算机进行对弈。下面将详细探讨这个项目中涉及的...
【VC用ActiveX控件做的五子棋!!】 在计算机编程领域,ActiveX控件是一种在Windows平台上广泛使用的组件技术,由微软公司开发。ActiveX控件是基于COM(Component Object Model)架构的小型可执行模块,它们可以...
"五子棋终结者2.0"便是这样一款具有里程碑意义的小程序,它标志着计算机在自由规则下执黑棋时能够确保必胜,实现了对五子棋的全面征服。 五子棋终结者2.0的核心在于其高效的搜索算法和优化的决策树。传统的五子棋AI...
【python游戏开发】项目实战:五子棋!
java课程设计小游戏网络版五子棋小游戏源码+java课程设计报告.zipjava课程设计小游戏网络版五子棋小游戏源码+课程设计报告.zipjava课程设计小游戏网络版五子棋小游戏源码+课程设计报告.zipjava课程设计小游戏网络版...
【网页版五子棋游戏源码详解】 网页版五子棋游戏是一款基于HTML5、CSS3和JavaScript技术实现的在线对弈游戏。由于无需数据库,它简化了部署流程,只需将源码上传至服务器,即可供用户直接访问并进行游戏。这种设计...
五子棋!!!!最益智的十大游戏之一!!!
HTML5网页版五子棋小游戏源码下载是一个包含所有必要组件和资源的压缩包,用于构建一个纯HTML5实现的在线五子棋游戏。这款小游戏可以让用户在网页上与电脑或者其他玩家对战,体验五子棋的乐趣。源码通常包括HTML、...
【Java网络版五子棋】是一款专为局域网用户设计的在线对弈游戏,它融合了经典五子棋玩法与现代网络通信技术,让用户在享受游戏乐趣的同时,也能进行实时的聊天交流,增强了游戏的社交性。这款应用的核心特点在于其...
在这个五子棋课程设计中,我们将会深入探讨如何利用嵌入式技术来开发一个能够实际运行的五子棋游戏。 首先,我们要理解嵌入式系统的架构。这通常包括硬件平台,如微控制器或SoC(System on Chip),以及在其上运行...
【标题】"单机版五子棋java代码实现"是一个基于Java编程语言开发的桌面游戏项目,旨在提供一个用户可以在本地计算机上玩的五子棋游戏。五子棋是一种策略性棋类游戏,两名玩家轮流在棋盘上下棋,目标是先连成五颗棋子...
网页版单机五子棋,javascript实现
【Java 网络版五子棋】是一个基于Java编程语言开发的在线对战游戏,它允许两位玩家通过网络连接进行实时对弈。这个项目涵盖了多个重要的编程概念和技术,包括图形用户界面(GUI)、网络通信、多线程以及游戏逻辑算法...
【五子棋网页版开发详解】 五子棋是一款广受欢迎的双人对弈游戏,它简单易懂,却又充满了策略性。在这个“五子棋(网页版)”项目中,开发者使用了纯JavaScript语言来实现游戏逻辑,展示了JavaScript在创建交互式...
JAVA编写的单机版五子棋JAVA编写的单机版五子棋JAVA编写的单机版五子棋JAVA编写的单机版五子棋JAVA编写的单机版五子棋JAVA编写的单机版五子棋JAVA编写的单机版五子棋JAVA编写的单机版五子棋
【网页版人机对战五子棋】是一种在网页上实现的互动游戏,它允许玩家与计算机进行对弈。这个游戏的开发涉及到了多种技术,包括前端界面设计、后端逻辑处理以及人工智能算法的运用。 首先,前端部分是用户与游戏交互...
网页版五子棋对战 支持以下核心功能: 用户模块: 用户注册, 用户登录, 用户天梯分数记录, 用户比赛场次记录. 匹配模块: 按照用户的天梯分数实现匹配机制. 对战模块: 实现两个玩家在网页端进行五子棋对战的功能.
在这个"单机版五子棋(修正版)"程序中,玩家可以与计算机进行对弈,由于是单机版,意味着玩家将同时扮演双方,进行模拟对抗。 【MFC框架详解】 MFC(Microsoft Foundation Classes)是微软提供的一种C++类库,...
五子棋单机版的小程序,通常采用预设的算法来模拟对手的思考,这些算法可能包括简单的搜索策略,如Minimax算法配合Alpha-Beta剪枝,或者是更高级的深度学习模型,如神经网络,以提供更智能的决策。 【开发过程】 在...
【Java单机版五子棋】是一款基于Java编程语言开发的桌面游戏,它利用Java的Swing库构建了用户友好的图形用户界面(GUI),使玩家可以在计算机上体验五子棋的乐趣。在这个项目中,我们可以深入探讨Java Swing、事件...