`
siyanglu
  • 浏览: 15323 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

初涉黑白棋之简单双人对战

 
阅读更多


          黑白棋,又称翻转棋,还有个说法叫奥赛罗棋,具体得名我并未去考

证。下棋方式很简单,是在游戏中通过相互翻转对方的棋子,最后以棋盘

上谁的棋子多来判断胜负。
      第一次接触到黑白棋是高四复读时。那时由于学校离家较远,为了方

便和家里联系,本人得到了生平第一部移动交通工具——一部与家中座机绑

定的小灵通。而小灵通上可怜的三个游戏,也成了无聊时瞎捣鼓的东西。

这三个游戏,一是贪吃蛇,而是打地鼠,这两样由于本人的手指实在是笨

拙,硬是反应不过来而放弃。于是经常玩的,也只有剩下的那个黑白棋了

。虽然没有刻意去了解规则,可玩多了也自然上手了,稍微还掌握了一点

小小的规律,以至到后面几乎每次都能赢。(现在看来那个机器算法还是

比较烂的……)说起来,小灵通上的这个游戏,竟陪我走过了那段最难熬

的岁月。(高考的孩子伤不起啊!第一年没考上接着去复读的更伤不起啊

有木有……)或许是有这种情愫在,当龙哥让我们选择项目时,我毫不犹

豫选择了黑白棋。(完了才发现整个小组除我之外大家做的都是五子棋…

…)
      废话不多说了,现在来说黑白棋的程序。首先是布置界面,方法与五

子棋无异,在参考了书上的代码之后很快便画出了棋盘,并在棋盘中心布

好了初始的四个棋子。

 
      接下来就是下子的问题了,这时才发现,事情没有开始想象的那么简

单。黑白棋下子并不像五子棋那样,只要有空置的位置就行,而是需要判

定,只有当所在点直线方向上有可以翻转的对方棋子以及己方棋子相夹时

才能下,并且下过之后还要翻转中间所夹的异色棋子。这里便涉及到两个

方面,判断下子和改变颜色。
      先说判断一个点是否能下的问题,这里先设了一个boolean型的二维

数组,命名为ifcan,用于记录每个格子是否可下的信息。这里单独用一

个方法来写以便反复调用。当然,在给某处赋值之前一定要遍历,在这里

的话,就需要遍历该点周围横竖斜八个方向。由于遍历所得的信息之后改

变颜色还要用到,于是单独分出了一个遍历的方法counts(),代码如下:

/**对某点遍历的方法*/
	public void counts(int i,int j){
			
		/**横向遍历*/
		//东向遍历
		if(i!=gs){
			for(int k =1 ;k<gs-i+1;k++){
				if(c[i+k][j]==0){count[0]=0;break;}
				else if(c[i+k][j]== cases ){break;}
				else{count[0]++;}		
			}
		}if(count[0]==0 || count[0]==gs-i){count[0]=0;}
		//西向遍历
		if(i!=1){
			for(int k =1 ;k< i ;k++){
				if(c[i-k][j]==0){count[1]=0;break;}
				else if(c[i-k][j]== cases ){break;}
				else{count[1]++;}		
			}
		}if(count[1]==0 || count[1]==i-1){count[1]=0;}
		/**纵向遍历*/
		//南向遍历
		if(j!=gs){
			for(int k =1 ;k< gs-j+1 ;k++){
				if(c[i][j+k]==0){count[2]=0;break;}
				else if(c[i][j+k]== cases ){break;}
				else{count[2]++;}		
			}
		}if(count[2]==0 || count[2]==gs-j){count[2]=0;}
		//北向遍历
		if(j!=1){
			for(int k =1 ;k< j ;k++){
				if(c[i][j-k]==0){count[3]=0;break;}
				else if(c[i][j-k]== cases ){break;}
				else{count[3]++;}		
			}
		}if(count[3]==0 || count[3]==j-1){count[3]=0;}
		/**斜向遍历*/
		//定义四个数代表斜向格数
		int ne,nw,se,sw;
			if(j<Config.ROWS+1-i){ne=j-1;sw=i-1;}else{ne=gs-i;sw=gs-j;}
			if(j<=i){nw=j-1;se=gs-i;}else{nw=i-1;se=gs-j;}
		//东北向遍历
		if(ne!=0){
			for(int k =1 ;k< ne+1 ;k++){
				if(c[i+k][j-k]==0){count[4]=0;break;}
				else if(c[i+k][j-k]== cases ){break;}
				else{count[4]++;}		
			}
		}if(count[4]==0 || count[4]==ne){count[4]=0;}
		//西北向遍历
		if(nw!=0){
			for(int k =1 ;k< nw+1 ;k++){
				if(c[i-k][j-k]==0){count[5]=0;break;}
				else if(c[i-k][j-k]== cases ){break;}
				else{count[5]++;}		
			}
		}if(count[5]==0 || count[5]==nw){count[5]=0;}
		//东南向遍历
		if(se!=0){
			for(int k =1 ;k< se+1 ;k++){
				if(c[i+k][j+k]==0){count[6]=0;break;}
				else if(c[i+k][j+k]== cases ){break;}
				else{count[6]++;}		
			}
		}if(count[6]==0 || count[6]==se){count[6]=0;}
		//西南向遍历
		if(sw!=0){
			for(int k =1 ;k< sw+1 ;k++){
				if(c[i-k][j+k]==0){count[7]=0;break;}
				else if(c[i-k][j+k]== cases ){break;}
				else{count[7]++;}		
			}
		}if(count[7]==0 || count[7]==sw){count[7]=0;}
	}	

 
      这里的count数组在之后的判断以及改变颜色时会用到。接下来是判

 

 

断了。遍历所得的count(i)代表八个方向中对每个方向而言在可下的情况

下所夹对方棋子数,若不可下,则为零。也就是说,只有当八个方向判定

都不可下时,该处信息才为false。于是有:

/**判断某点对当前子来说是否可下的方法*/
	public void ifcan(int i,int j){
		this.counts(i,j);
		int temp = 0;
		for(int t=0; t<8; t++){
			 temp = temp + count[t];	
		}if(temp==0){
			ifcan[i][j]=false;
		}else{
			ifcan[i][j]=true;cnt_t++;
		}
		/**最后将count数组置零,进行下一次判断*/
		for(int t=0; t<8; t++){
			count[t] = 0;
			}
	}

 
      下完子的同时要翻转中间的棋子,通过刚才得到的count数组,可以

 

 

很快写好,虽然每种都要写一遍,但原理是一样的。

/**改变颜色的方法*/
	public void change(int x, int y){
	
		//调用遍历的方法
		this.counts(x, y);
		
		if(count[0]!=0){
			for(int i=1;i<count[0]+1;i++){
				c[x+i][y]=cases;
				this.chessput(x+i, y);
			}
		}if(count[1]!=0){
			for(int i=1;i<count[1]+1;i++){
				c[x-i][y]=cases;
				this.chessput(x-i, y);
			}
		}if(count[2]!=0){
			for(int i=1;i<count[2]+1;i++){
				c[x][y+i]=cases;
				this.chessput(x, y+i);
			}
		}if(count[3]!=0){
			for(int i=1;i<count[3]+1;i++){
				c[x][y-i]=cases;
				this.chessput(x, y-i);
			}
		}if(count[4]!=0){
			for(int i=1;i<count[4]+1;i++){
				c[x+i][y-i]=cases;
				this.chessput(x+i, y-i);
			}
		}if(count[5]!=0){
			for(int i=1;i<count[5]+1;i++){
				c[x-i][y-i]=cases;
				this.chessput(x-i, y-i);
			}
		}if(count[6]!=0){
			for(int i=1;i<count[6]+1;i++){
				c[x+i][y+i]=cases;
				this.chessput(x+i, y+i);
			}
		}if(count[7]!=0){
			for(int i=1;i<count[7]+1;i++){
				c[x-i][y+i]=cases;
				this.chessput(x-i, y+i);
			}
		}
		for(int t=0; t<8; t++){
			count[t] = 0;
		}
		
	}

 
      另外,棋子的画法另用一个类写在了外面,无非是画实心圆而已,这

 

 

样看起来清爽了不少。在下完一个子之后,通过改变cases的值来更换下

棋方,在这里黑方为1,白方为-1。对于棋盘,给每个格子一个棋盘信息,

也是一个二维数组,名为c[][],黑为1,白为-1,无子为0。可以下棋之

后,则是判断输赢了,黑白棋的判断输赢很简单,即通过最后棋盘中棋子

的个数来判断,多的一方胜。所以,当每下一颗子之后,都要对棋盘进行

遍历以获得盘中每种颜色棋子的个数,以及对即将下子的一方而言可下的

信息。

for(int j=1; j< Config.ROWS; j++){
			for(int i=1; i< Config.COLUMNS; i++){
				if(c[i][j]==1){
					cnt_b++;ifcan[i][j]=false;//黑子个数加一
				}else if(c[i][j]==-1){
					cnt_w++;ifcan[i][j]=false;//白字个数加一
				}else{
					/**无子点确定对下轮cases的ifcan*/
				this.ifcan(i,j);
					}
			}
		}
		count_true = cnt_t; cnt_t=0;//对当前子而言可以下的地方的个数
		count_black = cnt_b; cnt_b=0;
		count_white = cnt_w; cnt_w=0;//总计棋盘中黑白棋的个数
		
		p4.setText("黑棋个数为:"+count_black);
		javax.swing.SwingUtilities.updateComponentTreeUI(p4);
		p5.setText("白棋个数为:"+count_white);
		javax.swing.SwingUtilities.updateComponentTreeUI(p5);
				
		/**根据个数的判断*/
		if(count_black==0){
			JOptionPane.showMessageDialog(null, "白棋胜!", "结束",JOptionPane.INFORMATION_MESSAGE);//盘中无黑子,白胜
		}if(count_white==0){
			JOptionPane.showMessageDialog(null, "黑棋胜!", "结束",JOptionPane.INFORMATION_MESSAGE);//盘中无白子,黑胜
		}if(count_true==0){
			cases=-cases;
			for(int j=1; j< Config.ROWS; j++){
				for(int i=1; i< Config.COLUMNS; i++){
					if(c[i][j]==0){
						this.ifcan(i,j);
					}
				}
			}
			count_true = cnt_t; cnt_t=0;//对当前子而言可以下的地方的个数
			if(count_true!=0){
				JOptionPane.showMessageDialog(null, "无子可下!", "换一方 ",JOptionPane.INFORMATION_MESSAGE);
			}else{
			if(count_black>count_white){
				JOptionPane.showMessageDialog(null, "黑棋胜!", "结束",JOptionPane.INFORMATION_MESSAGE);
			}else{
				JOptionPane.showMessageDialog(null, "白棋胜!", "结束",JOptionPane.INFORMATION_MESSAGE);
			}
		}
}//棋盘满时,所剩棋子多的一方胜

         到这里,一个简单的人人对战的黑白棋就写好了,之后会写人机对战的智能算法,现在这篇就告一段落了。最后再放张图吧。

  • 大小: 39.7 KB
  • 大小: 54.8 KB
分享到:
评论
1 楼 luozhong915127 2011-11-17  
有点嫉妒

相关推荐

    一个黑白棋游戏源码+项目说明(支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现).zip

    【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等...一个黑白棋游戏源码+项目说明(支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现).zip

    java黑白棋(人人对战)

    Java黑白棋游戏是一款基于Java编程语言开发的双人对战游戏。它允许两位玩家通过轮流翻转对方的棋子来争夺棋盘上的控制权。在这个游戏中,每一步操作都至关重要,因为策略性的布局和巧妙的反转是取胜的关键。下面我们...

    基于 Java 实现的黑白棋游戏,支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现

    【作品名称】:基于 Java 实现的黑白棋游戏,支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、...

    黑白棋人机对战C/C++

    黑白棋,又称翻转棋或反棋,是一种深受玩家喜爱的双人策略游戏。在这个"黑白棋人机对战C/C++"项目中,开发者利用C语言实现了一个可以在控制台内运行的人机对战系统。下面我们将深入探讨这个项目的相关知识点。 首先...

    java五子棋双人对战

    【Java五子棋双人对战】是一种基于Java编程语言实现的在线游戏,允许两位玩家通过网络进行实时对战。这款游戏的设计目标是提供一个简洁、交互式的平台,让玩家可以享受五子棋的乐趣。五子棋是一种策略性极强的两人...

    C++双人单人对战黑白棋

    6. **双人对战**:双人对战模式下,程序需要交替接收两个玩家的输入,并更新棋盘状态。 7. **错误处理**:良好的错误处理机制是任何程序不可或缺的一部分,例如检查用户输入的合法性,防止非法操作。 在实际开发...

    黑白棋C++实现

    滕讯小游戏黑白棋,用C++语言实现,可实现简单的双人对战与人机对战。

    基于蒙特卡洛树搜索MCTS的黑白棋游戏Java源码+使用说明(支持双人对战、人机对战).zip

    基于蒙特卡洛树搜索MCTS的黑白棋游戏Java源码+使用说明(支持双人对战、人机对战).zip基于蒙特卡洛树搜索MCTS的黑白棋游戏Java源码+使用说明(支持双人对战、人机对战).zip基于蒙特卡洛树搜索MCTS的黑白棋游戏Java源码...

    局域网黑白棋对弈C++实现报告

    《局域网黑白棋对弈C++实现报告》是一份详细介绍如何使用C++编程语言实现局域网内的黑白棋对战游戏的项目报告。这份报告不仅涵盖了游戏的基本规则和操作流程,还深入探讨了网络通信和多线程编程在游戏中的应用。下面...

    c++课设黑白棋

    黑白棋以其简单的规则和复杂的策略深度,成为了课余时间的理想消遣之一。为了满足学生在课余时间进行轻松娱乐的需求,胡冀川决定与队友赵元勃共同开发一个黑白棋游戏。他们旨在创造一款支持人机对战和双人对战的游戏...

    C++黑白棋游戏完全代码

    本课题设计并实现了一个可以单人或双人对战的黑白棋游戏系统,该系统采用C++语言在Microsoft Visual C++ 6.0下编写代码,采用VC中比较流行的MFC模板进行编程。系统不仅使人进行双人对战也可以进行单人与计算机的对战...

    黑白棋AI程序

    黑白棋,又称翻转棋或反棋,是一种深受玩家喜爱的双人策略游戏。在这个场景中,我们讨论的是一个黑白棋的AI程序。AI(Artificial Intelligence)在棋类游戏中的应用是计算机科学的一个重要分支,它涉及到算法设计、...

    一个黑白棋游戏,支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现。_Othello-game.zip

    一个黑白棋游戏,支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现。_Othello-game

    黑白棋研究(介绍黑白棋代码)

    黑白棋,又称翻转棋或反棋,是一种极具策略性的双人棋类游戏。在这个主题中,我们将深入探讨黑白棋的代码实现,主要基于C++编程语言。在提供的压缩包文件中,我们可以看到一系列与黑白棋相关的源代码文件和文档,...

    黑白棋人人对战实现(人机,网络暂不可用,自行编写)

    黑白棋,又称翻转棋或反棋,是一种深受玩家喜爱的双人策略游戏。本项目实现了黑白棋的人人对战模式,但不包含人机对战和网络对战功能,这意味着用户只能与真实玩家面对面进行游戏。项目使用了QT框架,这是一种跨平台...

    Java《基于MCTS(蒙特卡洛树搜索)实现黑白棋游戏(支持双人对战,人机对战,人机AI)》+项目源码+文档说明

    一个黑白棋游戏,支持双人对战,人机对战,人机AI使用MCTS(蒙特卡洛树搜索)实现。 - 不懂运行,下载完可以私聊问,可远程教学 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用...

    VC 游戏源码-黑白棋双人版.rar

    《VC 游戏源码-黑白棋双人版》是一个基于Visual C++(简称VC)开发的双人黑白棋游戏程序。源码包含了完整的功能模块,不仅提供了基本的游戏逻辑,还具备了一些高级特性,如时间统计、步数记录、游戏模式选择等。以下...

    cpp-带图形界面的黑白棋程序有保存悔棋联机对战与电脑对战等功能

    本文将详细讲解一个基于C++实现的带图形界面的黑白棋程序,该程序包含了保存、悔棋、联机对战以及电脑对战等多种功能。在深入探讨这些特性之前,我们首先了解一下黑白棋(也称为翻转棋或奥赛罗棋)的基本规则。黑白...

    16黑白棋_黑白棋源码_

    黑白棋,又称翻转棋或反棋,是一种双人对弈的策略棋类游戏,具有简单易学但深度丰富的特点。本压缩包包含的“黑白棋源码”提供了实现黑白棋游戏的人机对战功能,这对于我们理解游戏逻辑、算法设计以及Delphi编程语言...

    c++黑白棋小游戏c++黑白棋小游戏

    黑白棋,又称反棋、翻转棋,是一款策略型的双人对弈游戏,源自19世纪末的英国,后来在日本广受欢迎。在C++编程语言中实现黑白棋小游戏,可以作为学习面向对象编程、游戏逻辑设计以及用户交互的一个实践项目。源代码...

Global site tag (gtag.js) - Google Analytics