一、实验题目
在察哈尔右翼中旗等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站制作、成都网站设计 网站设计制作按需搭建网站,公司网站建设,企业网站建设,品牌网站制作,全网整合营销推广,成都外贸网站制作,察哈尔右翼中旗网站建设费用合理。
五子棋游戏。
二、问题分析
五子棋是双人博弈棋类益智游戏,由围棋演变而来,属纯策略型。棋盘通常15*15,即15行,15列,共225个交叉点,即棋子落点;棋子由黑白两色组成,黑棋123颗,白棋122颗。游戏规则为黑先白后,谁先五子连成一条直线谁赢,其中直线可以是横的、纵的、45度、135度。
本次Java编程我的目的是现实人机对战,即游戏者一方是人,另一方计算机。这就要求程序不仅要具备五子棋的基本界面,还要编程指导计算机与人进行对弈。为了使程序尽可能智能,我采用了贪心策略、传统搜索算法、极大极小博弈树算法,对应游戏玩家的3个等级:简单、中等、困难。
三、功能设计
我的程序基本功能是实现人机对弈五子棋。人和电脑交替下棋,谁先五子连成一条直线谁就赢。下面是我程序的功能模块:
1.等级设置
核心功能是实现不同策略与算法的对比运用,纯贪心策略实现简单等级对手,直接搜索算法实现中等等级对手,极大极小博弈树算法实现困难等级对手。对应程序中的3选1单选按钮。
2.悔棋功能
模拟栈机制实现人悔棋,不限步长的悔棋。对应程序中的悔棋按钮。
3.棋面绘制
根据不同机计算机的屏幕分辨率,绘制逼真的棋盘。
4.图片引入
两张古典的人物图片,生动模拟对弈双方。人物图片旁的黑白棋钵图片显示黑白棋归属。
5.背景设置
支持用户选择背景,包括棋盘、棋盘边框、窗口边框,彰显个性。
6.音乐播放
下棋时有棋子落地的声音,一方胜利时有五子连成一片的声音。同时在设置背景时相应的改变整个对弈过程中的背景音乐。
7.时间显示
在棋盘正上方有一模拟文本框显示当前棋局用时。
8.其他小功能
支持和棋、认输、开启新游戏、退出游戏等操作。
四、数据结构与算法设计
数据结构部分
1.当前棋局的存储结构
我的五子棋程序选择通常用到的15行*15列棋盘,可以开二维数组PositionFlag = new int[15][15],PositionFlag[i][j]为0表示(i,j)点尚无棋,为1表示(i,j)点是人的棋子,为2表示(i,j)点是机器的棋子。之所以选择二维数组,主要原因有两点:
1.本程序需要频繁随机访问15*15的交叉点,对应查询该点状态以及改变该点状态,随机访问是数组的特点。
2.15*15=225开二维数组的内存需求相对现在内存为2G及以上的计算机完全可以接受,且数组实现简单、操作方便。
基于以上两点,尽管创建动态的顺序表—链表可能可以节省少量内存(可以只存当前有棋的点,原数组对应位置为0的点可以不存),但选择数组的优势完全在上述两点体现了出来。
2.实现悔棋操作的数据结构
由于每次悔棋只需回退当前几步,后进先出原则,这正是栈这种典型数据结构的设计思想,于是我选择栈。我自己先写了用自定义数组模拟的栈,但由于是学Java语言且由于悔棋的存储空间需要随当前步数增大而增大(由于每局最多下225步,即最多要悔225步,所以自己开个225的数组完全可以避免存储空间自增长的问题且内存完全可以接受,之所以不用自定义数组而用ArrayList类主要是为了尝试Java中STL的用法),所有我最终改为用Java类库中的ArrayList类。
确定用ArrayList类实现栈机制后就必须考虑每个ArrayList单元具体存储什么。刚开始我存储的是当前的棋局,即整个局面,而每个局面对应一个二维数组,这样是很占用内存的。试想一下,在最坏情况下,225个ArrayList单元,每个单元存放一个15*15的二维数组,尽管225*15*15在Java的内存管理机制下不会爆栈,但也是极不划算的。之所以说不划算,是因为有更好的解决方案。由于每次悔棋只是在回退倒数一步,多步悔棋只需循环回退,所以可以只存储当前棋局最后一步的下法,对应一个二维点,完全可以自定义一个二维坐标类chessOneStep。
算法设计部分
Java语言是面向对象的语言。我在进行五子棋游戏编程是总共传创建了11个自定义的类。在编写程序的过程中,我有一个明显的体验就是面向对象编程就是一项有关对象设计和对象接口技术,很多关键的技术就是如何设计自定义的对象。
下面我先概括给出我的所有类的作用:
1.mainFrame类:主框架类,我应用程序的入口;
2.chessPositon类:主控类,这个类是我程序的核心类,负责控制双方的下棋,以及调用其他的类完成当前棋局的显示绘制;
3.chessPanel类:面板类,调用其他底层类完成当前棋局的显示绘制;
4.chessBoard类:棋盘绘制类,负责棋盘的绘制;
5.chessImage类:文件类,包含各种资源(背景图片、背景音乐)以及静态全局变量(public static Type);
6.chessButton类:组件类,定义各种组件,包括按钮、单选按钮、文本框等;
7.chessMusic类:音乐类,负责调用Java库类完成背景音乐、下棋音乐、取胜音乐等的播放;
8.chessPiece类:棋局类,定义棋局二维数组数据结构并完成相关操作;
9.chessList类:栈类,完成悔棋等操作;
10. chessOneStep类:棋子类,定义每步坐标以及下在该处获得的估价值;
11.myCompare类:排序类,完成chessOneStep类的自定义排序
详细设计
1.mainFrame类
作为我的五子棋程序的主类,mainFrame类主要实例化相关的对象,如chessbutton,chessborad等,从而完成框架的创建。更重要的是实例化chessposition,这是本程序的核心类,控制游戏双方行棋过程完成人机互动下棋,然后将MyChessPosition与鼠标响应addMouseListener()关联起来。
2.chessMusic类
一个好的游戏必须给人一种身临其境的感觉,而声音是营造这种氛围的重要因素。参照网上各游戏运行商的音乐配置,我选择相关逼真的声音。包括背景音乐、下棋棋子落到棋盘发出的声音以及一方胜出的配乐。所有这些功能的实现,依赖于自定义的chessMusic类,采用AudioInputStream配合Clip的方式完成音乐播放的软硬件工作,然后定义两个接口chessmusic(String Name)和Stop(),前者完成播放功能,后者完成关闭当前音乐功能。因为音频文件相对较大,而我的程序提供在不同背景乐之间切换的功能,所以在打开另一个音频文件之前必须关闭前一个正在播放的音频文件,防止出现溢出。
3.chessImage类
适当的动画或图片能给游戏玩家带来美的体验。所以我的五子棋程序界面在不失和谐的前提下引入了尽可能多的图片,包括对弈双方、棋钵等。图片引入的具体工作通过语句import javax.imageio.ImageIO完成。同时,由于图片要在用到它的类中被访问,为了避免频繁调用函数,我直接将图片相关联的对象定义为public static,表明是公用的、静态的。进一步引申开去,我将程序中用到的静态全局变量都定义在chessImage类中。具体如下:
public static Date begin;//每局开始时间
public static Date cur;//每局结束时间
public static chessOneStep LineLeft;//结束端点1
public static chessOneStep LineRight;//结束端点2
public static boolean IsGameOver;//是否只有一方获胜
public static int ColorOfBackGround[][]= {{255, 227, 132},{0,255,127},{218,165,32}};//背景颜色
public static int ColorOfWindows[][]= {{ 60,179,113},{245,245,245},{122,122,122}};//背景颜色
public static int WitchMatch;//背景搭配
public static String MusicOfBackGround;//背景音乐
public static int CurrentStep;//记录当前步数
public static int Rank;//设置难度等级
public static boolean IsSurrender;//判断是否认输
public static boolean IsTie;//判断是否认输
public static String Message;//输出提示信息
public static Image IconImage;// 图标
public static Image blackBoard;//白棋盘
public static Image whiteBoard;//黑棋盘
public static Image blackChess;// 白棋棋子图片
public static Image whiteChess;// 白棋棋子图片
public static Image RightPlayer;//白棋棋罐图片
public static Image LeftPlayer;//白棋玩家头像图片
public static String path = "src/";// 图片的保存路径
4.chessButton类
这个是程序的组件类。定义了各种功能键,完善程序功能,营造逼真的人机对战游戏效果。分为3类:效果。。
(1)、按钮组件
本程序有5个按钮,支持和棋、认输、新游戏、退出、悔棋等。认输和和棋按钮终止当前的棋局,给出相应的提示信息;退出按钮调用系统System.exit(0)的函数正常返回;悔棋按钮调用后面要介绍的chessList类实现悔棋;新游戏按钮则刷新当前棋局准备下一轮,要将记录当前棋局的二维数组全部置0,刷新当前棋局开始时间等。
(2)、单选按钮组件
游戏界面支持设置个性化界面,包括背景颜色与背景音乐,跟重要的一点是设置难度(简单、中等、困难)。单选按钮只能多选一。背景颜色主要是存储相关颜色搭配方案的RGB颜色,开2维数组,即对应RGB3原色数组的一维数组,然后通过改变WitchMatch全局变量的值来有用户自己选择颜色搭配,不同的颜色搭配对应不同的背景音乐表达一致的主题。难度设置主要是改变计算机的下棋算法,不同难度通过Rank判断进入不同的程序分支,实现不同智能等级的计算机下棋水平。
(3)、文本框
在不同的单选按钮前添加相应的文本框,提示用户可以实现的功能。同时我用颜色模拟出显示当前棋局耗用时间的文本框。
不论按钮还是单选按钮都要关联相应的消息,把相应功能的实现放在消息响应处理函数理。这些主要是实现Java库提供的消息响应接口里的方法。
5.chessPiece类
主要完成当前棋面的存储,存储棋面的数据结构为二维数组int[][] PositionFlag;然后定义获取、设置某点以及整个棋面的状态的方法。
(1)、SetPositionFlag(int x, int y, int flag)//设置(x,y)处的状态为flag
(2)、GetPositionFlag(int x, int y)//获取(x,y)处的状态
(3)、SetAllFlag(int [][]NewFlag)//设置当前整个棋面的状态为NewFlag
(4)、GetAllFlag()//获取当前整个棋面的状态
(5)、DrawChessPiece(Graphics g)//绘制当前局面的棋子
由于本类比较重要,所以附上了代码,见源代码1。
6.chessBoard类
功能为绘制棋盘线。由于围棋的棋盘比较复杂,横线、竖线较多,且为了使棋盘美观,还要自定义窗口边框、棋盘边框、对弈双方边框等,对线宽、线型也有一定要求。有时要单像素线条,有时要多像素线条。对于多像素线条,我主要用了2种方法。
方法一:
在需要绘制多像素线条处首先绘制一条单像素线,然后根据线宽要求上下平移适当像素达到绘制多像素的目的。这样的方法适合绘制水平线或竖直线,绘制其他斜率的线条容易造成走样。在没有想到比较好的反走样编程思想后我选择了调用Java库中已经封装好的函数。
方法二:
为了克服方法一绘制非水平或竖直线时造成的走样,同时也为了更进一步学习Java语言,我猜想肯定会有类似OpenGL中设置线宽的画刷,于是上网百度找到了相应的画刷Stroke类。通过Java库实现绘制不同线宽的直线,达到了反走样效果。
7.chessOneStep类
这个类是为了配合chessList类实现悔棋以及在计算机下棋算法实现返回有效状态点而设计的。主要数据成员为
private int x,y,weight;//其中x,y表示点坐标,weight表示将棋下到该点获得的估价值。
主要方法如下:
(1)、GetX()//获得当前对象的x坐标
(2)、GetY()//获得当前对象的y坐标
(3)、GetWeight()//获得当前对象的(x,y)处的估价值
8.chessList类
程序支持悔棋功能,为了实现悔棋,自定义了chessList类。这个类主要通过引入java.util.ArrayList和java.util.List实现集合的数据类型。然后自定义一些方法,如下:
(1)、AddStep(chessOneStep OneStep)//添加一步棋到List中
(2)、GetSize()//获得当前List的大小
(3)、ClearList()//清空List
(4)、RemoveLast()//删去List中的最后元素
由于每次删除当前List中的最后一个元素,实现后进先出,所以可以模拟栈的功能实现悔棋。
9.myCompare类
由于在计算机下棋的极大极小博弈树算法中需要对自定义对象chessOneStep按weight进行排序,所以引入了myCompare类,通过实现Comparator接口中的compare方法完成自定义对象排序。
10.chessPanel类
程序的自定义面板类,主要负责完成当前框架内容的显示。这是一个重要的与框架和图形显示密切相关的类。主要数据成员为
private chessboard MyChessBoard;//当前显示棋盘
private chesspiece MyChessPiece;//当前显示整个棋面的状态
主要方法如下:
(1)、chesspanel(chessboard MyChessBoard1, chesspiece MyChessPiece1)//构造函数,分别用MyChessBoard1和MyChessPiece1初始化MyChessBoard和MyChessPiece
(2)display(chessboard MyChessBoard1, chesspiece MyChessPiece1)//自定义显示回调函数,调用repaint()完成重新绘制游戏界面
(3)、paintComponent(Graphics g)//核心方法,调用各种函数完成具体的绘制工作
11.chessPositon类
程序算法核心类,总的功能是控制人和计算机轮流下棋,以及调用chessPanel类中的display(chessboard , chesspiece )方法完成界面的实时刷新。关于chessPositon类,我在此将重点介绍。chessPosition类的主要数据成员如下:
private static chessboard MyChessBoard;//当前显示棋盘
public static chesspiece MyChessPiece;//当前显示整个棋面的状态
private static chesspanel Mychesspanel;////当前显示面板
public static chesslist MyChessList=new chesslist();//当前下棋集合,用于悔棋
final private static int INF = (1 30); // 表示正无穷大的常量,用于极大极小博弈数搜索算法
public static boolean CanGo;//控制当前下棋一方
类的设计集中体现在成员方法的设计上。实现人机对战,只有语言是远远不够的,还要加入算法,用算法引导计算机下棋。下面介绍该类的方法成员:
(1)、chessposition(chesspanel , chessboard ,chesspiece ) //带有参数的构造函数
(2)、chessposition()
不带参数的构造函数
(3)、mouseClicked(MouseEvent event)
鼠标响应函数,负责人的下棋,根据鼠标点击的位置转换得到所在棋盘的相对位置。如果该位置不合法,即超出棋盘有效范围,点击无响应;如果该位置上已有棋,弹出消息框给出提示。这二者都要求重新给出下棋位置,即当前鼠标响应无效…直到点击到棋盘有效区域。
(4)、IsOver(int[][] Array,int x,int y)
判断当前int[][]Array对应的棋局是否结束,即一方五子连成一条直线。此处有两种思路,一种对当前棋面上的所有棋子都进行一次判断,具体为水平方向、竖直方向、与水平线成45度方向、与水平线成135度方向,只要有一个方向五子连成一条直线就说明有一方获胜,游戏结束;另一种思路为只在当前下棋的4个方向进行判断,我的程序采用的是第二种,所以IsOver方法除了int[][]Array参数外,还有x,y参数,(x,y)表示当前下棋的坐标点。
(5)display()
通过调用自定义面板类的显示回调函数用于重新显示游戏界面,达到每下一步棋及时更新游戏界面的目的。
(6)、GetValue(int flag, int num)
估值函数,根据经验把棋局分成只有1颗棋相连,2颗棋相连且两端被封死,2颗棋相连且一端封死另一端活的,2颗棋相连且两端都是活的,同理3颗棋、4颗棋也各自可分3种情况。不同的情况对应不同的估价值。估价值的设定是决定计算机一方是否智能的一个关键因素。
(7)、GetPredictValue(int flag, int num)
对未连成一片但通过再下一颗子就能连成一片的局面进行估值,这在双方下棋的有限步骤内是能产生重要影响的。如果每局棋仅考虑当前一步,是不可取的。
(8)、Evaluate(int[][] Array, int x, int y)
根据棋面具体情况以及预先设定的估值函数,对某个点对应的局面进行评估。由于每次双方只能下一颗棋,所以可以每次取当前局面的所有点中对应估值最大值点的估值作为整个局面的估值。
(9)、GetGreedNext()
计算机下棋方法1,对应难度等级为简单,采用贪心思想。每次下棋前在求得最有利点下棋,而是否最有利只是通过一步评估。算法伪码描述为:
Max取负无穷大
for(行i从0到15)
{
For(列j从0到15)
{
If((i,j)对应的位置无棋)
{
a.假设放上一颗由人控制的棋,求估价值;
b.假设放上一颗由计算机控制的棋,求估价值;
c.取二者中较大值作为(i,j)处的估价值tmp;
d.取tmp与Max较大值赋值给Max.
}
}
}
最终Max对应的点就是当前整个局面中最大的估值点。至于上述为什么要考虑双方都在该点下棋的情况呢?主要原因为下五子棋是个攻防兼备的过程,不仅要考虑自己对自己最有利,还要考虑对对手最不利,通俗来讲就是在自己赢的时候不能让对手先赢。
(10)、GetSearchNext(int LookLength)
derectSearch(int [][]Array,boolean who,int deepth)
计算机下棋方法2:直接搜索法,对应难度等级为中等。
每步棋最多有225个不同下法,若采用直接搜索法则对应的孩子节点有225个(在下棋过程中会逐渐减少),即每层有最多225个节点待扩展,这就决定了直接搜索进行不超过2次—主要原因有两点:
a.采用深度优先搜索需要递归,递归中状态过多可能会爆栈,我们知道递归是用栈机制来实现的;采用宽度优先搜索又需要存储为扩展的节点,这对内存容量要求很高。
b.不管深搜还是广搜,在时间复杂度为O(N^m)的情况下都是不能接受的。其中N为当前棋局的待扩展节点,最大225;m为搜索的深度。
综上所述,在采用直接搜索法时搜索深度不能太深,严格来说是应该控制在2层以内,在计算机运算速度在10^7次每秒的情况下,理论和实验都表明超过2层就会变得很慢且这种趋势成指数级增长。
直接搜索算法伪代码为
GetSearch(boolean flag,int deep)
{
如果deep等于0,返回当前棋局估值;
for(行i从0到15)
{
For(列j从0到15)
{
If((i,j)对应的位置无棋)
{
如果轮到计算机下棋,置标志位为2
GetSearch(!flag,deep-1);
如果轮到人下棋,置标志位为1;
GetSearch(!flag,deep-1);
}
}
}
}
(11)、GetMinMaxsearchNext(int LookLength)
MinMaxsearch(int [][]Array,boolean who, int deepth)
计算机下棋算法3:极大极小博弈树法,对应难度等级为困难。五子棋是个博弈游戏,当前在寻找对自己最有利的下棋点时要尽可能保证对对手最不利,这种思想可以用极大极小博弈树
这游戏设计的,电脑哪有胜算啊,点数到了20就全都放弃了,永远也到不了100啊。以下是代码:
package com.sino.baiduzhidao.throwDie;
import java.util.Random;
/**
* 骰子
* @author Yanghl
*
*/
public class Die implements Runnable {
private Random r;
private int point;
public Die() {
r = new Random();
}
/**
* 获得骨子点数
* @return 骰子点数
*/
public int getPoint() {
return point;
}
@Override
public void run() {
//设置骰子点数为1-6的随机数
point = r.nextInt(6) + 1;
System.out.print(point + " ");
}
}
package com.sino.baiduzhidao.throwDie;
public class PairOfDice {
/**
* 骰子1
*/
private Die die1;
/**
* 骰子2
*/
private Die die2;
public PairOfDice() {
die1 = new Die();
die2 = new Die();
}
/**
* 掷出两个骰子,并打印结果
*/
public void throwDie() {
System.out.print("骰子点数:");
//启用两个线程,分别转动两个骰子,模拟两个骰子同时被掷出
Thread t1 = new Thread(die1);
Thread t2 = new Thread(die2);
t1.start();
t2.start();
try {
//等待骰子结束
t1.join();
t2.join();
System.out.println();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 两个骰子点数都为6
* @return
*/
public boolean isDouble6() {
if(die1.getPoint() == 6 die2.getPoint() == 6) {
return true;
}
return false;
}
/**
* 只有一个骰子点数为1
* @return
*/
public boolean isSingle1() {
if(die1.getPoint() == 1 || die2.getPoint() == 1) {
if(isDouble1()) {
return false;
}
return true;
}
return false;
}
/**
* 两个骰子点数都为1
* @return
*/
public boolean isDouble1() {
if(die1.getPoint() == 1 die2.getPoint() == 1) {
return true;
}
return false;
}
/**
* 获取两个骰子点数总和
* @return
*/
public int getPointNum() {
return die1.getPoint() + die2.getPoint();
}
public Die getDie1() {
return die1;
}
public Die getDie2() {
return die2;
}
}
package com.sino.baiduzhidao.throwDie;
public class BoxCars {
public static void main(String[] args) {
PairOfDice pod = new PairOfDice();
int times = 0;
for(int i=0;i100;i++) {
pod.throwDie();
if(pod.isDouble6()) {
times ++;
}
}
System.out.println("掷骰子100次,都是6的次数:" + times);
}
}
以下是人机大战的代码:
package com.sino.baiduzhidao.throwDie;
/**
* 玩家类
*/
public class Player {
/**
* 玩家名称
*/
private String name;
/**
* 掷骰子总数
*/
private int throwTimes;
/**
* 总点数
*/
private int pointNum;
public Player(String name) {
this.name = name;
this.pointNum = 0;
this.throwTimes = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getThrowTimes() {
return throwTimes;
}
public void setThrowTimes(int throwTimes) {
this.throwTimes = throwTimes;
}
public int getPointNum() {
return pointNum;
}
public void setPointNum(int pointNum) {
this.pointNum = pointNum;
}
}
package com.sino.baiduzhidao.throwDie;
import java.util.Scanner;
public class Pig {
/**
* 电脑默认最大点数,超过后均放弃掷骰子
*/
private static int COMPUTER_DEFAULT_MAX_POINT = 20;
/**
* 目标分数
*/
private static int TARGET_POINT = 100;
/**
* 一对骰子
*/
private PairOfDice pod;
/**
* 玩家
*/
private Player player;
/**
* 电脑
*/
private Player computer;
/**
* 构造函数,初始化骰子
*/
public Pig() {
pod = new PairOfDice();
player = new Player("player");
computer = new Player("computer");
}
/**
* 开始游戏
*/
public void startPlay() {
while(true) {
//先玩家,后电脑
System.out.println("-----------------玩家---------------");
if(isThrowDie()) {
if(playerThrow(player)) {
break;
}
} else {
System.out.println("放弃掷骰子");
}
System.out.println();
System.out.println("-----------------电脑---------------");
if(computer.getPointNum() COMPUTER_DEFAULT_MAX_POINT) {
if(playerThrow(computer)) {
break;
}
} else {
System.out.println("放弃掷骰子");
}
System.out.println();
}
}
/**
* 玩家掷骰子,并返回玩家总分是否达到TARGET_POINT
* @return
*/
private boolean playerThrow(Player p) {
pod.throwDie();
//掷骰子次数 +1
p.setThrowTimes(p.getThrowTimes() + 1);
if(pod.isDouble1()) {
//掷出两个1,分数清0
p.setPointNum(0);
System.out.println("两个点数均为1,总分清0");
} else if(pod.isSingle1()) {
//掷出单个1,不加分
System.out.println("有一个点数为1,不能计入总分");
} else {
p.setPointNum(p.getPointNum() + pod.getPointNum());
}
System.out.println("当前总分:" + p.getPointNum());
//判断玩家总分是否达到TARGET_POINT
if(p.getPointNum() = TARGET_POINT) {
System.out.println("Game Over! " + p.getName() + " win!");
return true;
} else {
return false;
}
}
/**
* 选择是否掷骰子
* @return
*/
private boolean isThrowDie() {
Scanner sc = new Scanner(System.in);
System.out.print("选择是否掷骰子(Y:掷骰子; N:放弃):");
while(true) {
String in = sc.nextLine();
if("y".equalsIgnoreCase(in)) {
return true;
} else if("n".equalsIgnoreCase(in)) {
return false;
} else {
System.out.print("请选择Y/N:");
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
new Pig().startPlay();
}
}
在日常学习、工作抑或是生活中,大家总免不了要接触或使用作文吧,作文根据体裁的不同可以分为记叙文、说明文、应用文、议论文。写起作文来就毫无头绪?下面是我为大家收集的人机大战作文,仅供参考,希望能够帮助到大家。
20xx年,地球大部分人的工作都被机器人代替,人类除了基本的需求,什么事都不做,米兰觉得,人类将会被机器人所代替。于是,他设计了一个完美的计划,并秘密的开始招人……
要找什么样的人呢?米兰根据需求列出了几个要求:一:要会编写程序,不然那什么去对付机器人二:必须敏捷力高,最好当过兵或特工。想好条件后,他发给了他弟弟米森。为什么要发给他弟弟呢?因为他弟弟是个商人,找几个人还是可以的。
人很快就找到好了,第一个人是哈尔,是一名专业的程序员,因父母都是部队里边的,所以当过几年兵。第二个人是安娜,大学生,计算机专业,拿过NOI的二等奖。第三个是彼得,曾经当过特工,并且对电脑和编写程序专门的学习过。“不错,还是米森靠谱”米兰高兴地说道。找到人后,就要开始讲计划了。米兰把他们找来,对他们说:“计划是这样的,我会先给你们每人一个智能手环,方便联系和输入代码,至于如何输代码,只需要将手环上的U盘拔下来,插到需要输入的USB口就可以了。首先我和彼得先偷偷的潜入市政厅,为你们接下来的行程一路开绿灯。而哈尔,你需要做的就是找到总机器人给他输入入侵代码。安娜,你需要一直在实验室里等待着哈尔的消息,收到消息后,你需要将提前准备好的优盘插入电脑,明白了吗?对了,记得带上你们的武器!”“我们明白了!会带上武器的.,放心吧!”第二天,六点,米兰和彼得偷偷的潜入了市政厅的时候,被机器人发现了!机器人正准备杀掉他俩时,米兰观察到了它的USB插口,将带有入侵程序的U盘插了进去,快速的输入了“解除攻击模式”的代码,并调出了市政厅的地图、机器人所的分布的位置和机器人的基本档案,并把它拷到了自己和彼得的手环上。
“队长,这些机器人主要分布在控制室和资料库,而我们的目的地就是控制室,怎么办?”彼得问道。“没事,我们只需要偷偷地潜入控制室,然后把程序发给哈尔,再屏蔽所有能探测到我们的信号,哈尔就相当于一个中转站,再让哈儿发给安娜。安娜输入程序就可以了!”米兰说道。接下来,事情进行的很顺利,他们成功潜入总控制室,将程序发给哈尔,立马屏蔽了所有的探索到的信号了。眼看一个机器人冲过来了,彼得找好角度,按下手中激光剑的开关,“碰”的一声,机器人爆了。哈尔发来短信,说安娜已经成功了。果然,所有的机器人全部爆了。他们成功了,不只是他们成功了,是人类成功了!这场战争,是人类获胜了!
/**
*
*/
package com.efounder.gwt.action;
import java.util.HashMap;
import java.util.Map;
import poc.shared.annotations.reflection.ClassForNameAble;
import com.efounder.builder.meta.bizmodel.SYS_MDL_CTN;
import com.efounder.gwt.action.utils.ActionUtils;
import com.efounder.gwt.form.application.util.FormScriptUtil;
import com.efounder.gwt.form.base.ActionComponent;
import com.efounder.gwt.form.base.DataSetComponent;
import com.efounder.gwt.model.FilterDataSet;
import com.efounder.gwt.model.FormModel;
import com.gwtent.reflection.client.Reflectable;
/**
* 创建单据分录或明细
* @author xiewanzhi
* @datetime 2015年3月30日 上午9:38:34
*/
@ClassForNameAble
@Reflectable
public class FormAddItemAction extends ActionComponent implements IFormAction{
public FormAddItemAction() {
super.setActionText("增加");
}
private FormModel formModel = null;
/**
* 获取表单模型
* @return
*/
public FormModel getFormModel() {
return formModel;
}
/**
* 设置表单模型
* @param formModel
*/
public void setFormModel(FormModel formModel) {
this.formModel = formModel;
}
private String CTN_ID = null;
/**
* 内容id
* @return
*/
public String getCTN_ID() {
return CTN_ID;
}
/**
* 设置内容id
* @param cTN_ID
*/
public void setCTN_ID(String cTN_ID) {
CTN_ID = cTN_ID;
}
private String ctnType = SYS_MDL_CTN._BIZ_CTN_TYPE_JIDS_;
/**
* 分录类型:分录(SYS_MDL_CTN._BIZ_CTN_TYPE_JIDS_)还是辅助分录(SYS_MDL_CTN._BIZ_CTN_TYPE_JPDS_)
* @return
*/
public String getCtnType() {
return ctnType;
}
/**
* 分录类型:分录和明细
* @param ctnType
*/
public void setCtnType(String ctnType) {
this.ctnType = ctnType;
}
/**
* 数据集组件,FormModel,过滤器FilterDataSet等
*/
private DataSetComponent dataSetComponent = null;
/**
* 数据集组件,FormModel,过滤器FilterDataSet等
* @return
*/
public DataSetComponent getDataSetComponent() {
return dataSetComponent;
}
/**
* 设置数据集组件,FormModel,过滤器FilterDataSet等
* @param dataSetComponent
*/
public void setDataSetComponent(DataSetComponent dataSetComponent) {
this.dataSetComponent = dataSetComponent;
}
/**
* 执行添加分录操作
*/
@Override
public Object doAction() {
// 检查模型
assert formModel != null : "添加分录action没有关联表单模型FormModel";
// 检查内容ID
assert CTN_ID != null !"".equals(CTN_ID) : "添加分录action没有设置内容id";
MapString, Object args = new HashMapString, Object();
//执行脚本
if("0".equals(FormScriptUtil.executeCompScripts(this,scriptContext, "beforeAdd", this, args))){
return null;
}
// 增加分录
if ( SYS_MDL_CTN._BIZ_CTN_TYPE_JIDS_.equals(ctnType) ) {
if ( dataSetComponent == null ) {
formModel.setCopy(isCopyRow);
formModel.createItem(CTN_ID, isAppend, null);
}
else {
// add by LiChao 使用数据集过滤集时创建一条分录
if( dataSetComponent instanceof FilterDataSet ){
formModel.setCopy(isCopyRow);
((FilterDataSet) dataSetComponent).createItem(CTN_ID);
}else
{
formModel.setCopy(isCopyRow);
((FormModel)dataSetComponent).createItem(CTN_ID, isAppend, null);
}
}
}
// 添加辅助分录
else if ( SYS_MDL_CTN._BIZ_CTN_TYPE_JPDS_.equals(ctnType) ) {
if ( dataSetComponent == null ) {
formModel.setCopy(isCopyRow);
//modified by LiChoa 执行添加辅助分录明细动作
formModel.createPart(CTN_ID);
} else {
// add by LiChao 使用数据集过滤集时创建一条明细
if( dataSetComponent instanceof FilterDataSet ){
((FilterDataSet) dataSetComponent).createPart(CTN_ID);
}else{
formModel.setCopy(isCopyRow);
((FormModel)dataSetComponent).createPart(CTN_ID, isAppend,"");
}
}
}
//执行脚本
FormScriptUtil.executeCompScripts(this,scriptContext, "endAdd", this, args);
return null;
}
/**
* 更新button状态
*/
@Override
public void doUpdate() {
if ( formModel == null ) {
this.setEnabled(false);
return;
}
// 通常单据提交之后,增加按钮不可用
if ( formModel.isEditing() ) {
this.setEnabled(true);
} else {
this.setEnabled(false);
}
//根据属性配置检查
this.setEnabled(ActionUtils.canEnable(this));
//formmodel可编辑时设置该action不可编辑 chenkai2016年10月24日
if (!canEdit) {
this.setEnabled(false);
}
//enabled = ActionUtils.canEnable(this);
super.doUpdate();
}
private boolean isCopyRow = false;
/**
* 是否复制上一行
* @return
*/
public boolean isCopyRow() {
return isCopyRow;
}
// baiguanghong 获取是否复制上一行
public boolean getIsCopyRow() {
return isCopyRow;
}
public void setIsCopyRow(boolean isCopyRow) {
this.isCopyRow = isCopyRow;
}
private boolean isAppend = false;
/**
* 是否追加。默认false;
* @return
*/
public boolean isAppend() {
return isAppend;
}
public void setIsAppend(boolean isAppend) {
this.isAppend = isAppend;
}
boolean canEdit = true;
/**
* 设置不可编辑 chenkai2016年10月24日
* @param canEdit
*/
public void setCanEdit(boolean canEdit) {
this.canEdit = canEdit;
}
@Override
public void register() {
super.register();
registerAciton();
}
public native void registerAciton() /*-{
this.getActionText = this.@com.efounder.gwt.action.FormAddItemAction::getActionText();
this.setCanEdit = this.@com.efounder.gwt.action.FormAddItemAction::setCanEdit(Z);
this.setFormModel = this.@com.efounder.gwt.action.FormAddItemAction::setFormModel(Lcom/efounder/gwt/model/FormModel;);
this.setDataSetComponent = this.@com.efounder.gwt.action.FormAddItemAction::setDataSetComponent(Lcom/efounder/gwt/form/base/DataSetComponent;);
}-*/;
}
package cn.xnec;
import javax.swing.JOptionPane;import java.util.Random;
class RandNumber {
public static void main(String args[]) {
String str = JOptionPane
.showInputDialog("人机大战开始,输入0表示拳头,\n1表示剪刀,2表示布,3退出");
Random sc = new Random();
int n = sc.nextInt(3);
int i = 0, j = 0, k = 0;
while (str.matches("0|1|2|3")) {
if (Integer.parseInt(str) == 3) {
JOptionPane.showMessageDialog(null, "游戏结束,你玩了" + (i + j + k)
+ "次", "结果", JOptionPane.PLAIN_MESSAGE);
break;
} else if (Integer.parseInt(str) == n) {
i++;
JOptionPane.showMessageDialog(null, "平局" + i + "次", "结果",
JOptionPane.PLAIN_MESSAGE);
} else if ((Integer.parseInt(str) - i) == -1
|| (Integer.parseInt(str) - i) == 2) {
j++;
JOptionPane.showMessageDialog(null, "你赢了" + j + "次", "结果",
JOptionPane.PLAIN_MESSAGE);
} else {
k++;
JOptionPane.showMessageDialog(null, "你输了" + k + "次", "结果",
JOptionPane.PLAIN_MESSAGE);
}
str = JOptionPane.showInputDialog("请输入数字[0,3]");
n = sc.nextInt(3);
}
JOptionPane.showMessageDialog(null, "你输入的数字不对,自动退出游戏", "结果",
JOptionPane.PLAIN_MESSAGE);
}
}
人机的没有,不过自己打自己的有。
------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class mypanel extends Panel implements MouseListener
{
int chess[][] = new int[11][11];
boolean Is_Black_True;
mypanel()
{
Is_Black_True = true;
for(int i = 0;i 11;i++)
{
for(int j = 0;j 11;j++)
{
chess[i][j] = 0;
}
}
addMouseListener(this);
setBackground(Color.BLUE);
setBounds(0, 0, 360, 360);
setVisible(true);
}
public void mousePressed(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
if(x 25 || x 330 + 25 ||y 25 || y 330+25)
{
return;
}
if(chess[x/30-1][y/30-1] != 0)
{
return;
}
if(Is_Black_True == true)
{
chess[x/30-1][y/30-1] = 1;
Is_Black_True = false;
repaint();
Justisewiner();
return;
}
if(Is_Black_True == false)
{
chess[x/30-1][y/30-1] = 2;
Is_Black_True = true;
repaint();
Justisewiner();
return;
}
}
void Drawline(Graphics g)
{
for(int i = 30;i = 330;i += 30)
{
for(int j = 30;j = 330; j+= 30)
{
g.setColor(Color.WHITE);
g.drawLine(i, j, i, 330);
}
}
for(int j = 30;j = 330;j += 30)
{
g.setColor(Color.WHITE);
g.drawLine(30, j, 330, j);
}
}
void Drawchess(Graphics g)
{
for(int i = 0;i 11;i++)
{
for(int j = 0;j 11;j++)
{
if(chess[i][j] == 1)
{
g.setColor(Color.BLACK);
g.fillOval((i + 1) * 30 - 8, (j + 1) * 30 - 8, 16, 16);
}
if(chess[i][j] == 2)
{
g.setColor(Color.WHITE);
g.fillOval((i + 1) * 30 - 8, (j + 1) * 30 - 8, 16, 16);
}
}
}
}
void Justisewiner()
{
int black_count = 0;
int white_count = 0;
int i = 0;
for(i = 0;i 11;i++)//横向判断
{
for(int j = 0;j 11;j++)
{
if(chess[i][j] == 1)
{
black_count++;
if(black_count == 5)
{
JOptionPane.showMessageDialog(this, "黑棋胜利");
Clear_Chess();
return;
}
}
else
{
black_count = 0;
}
if(chess[i][j] == 2)
{
white_count++;
if(white_count == 5)
{
JOptionPane.showMessageDialog(this, "白棋胜利");
Clear_Chess();
return;
}
}
else
{
white_count = 0;
}
}
}
for(i = 0;i 11;i++)//竖向判断
{
for(int j = 0;j 11;j++)
{
if(chess[j][i] == 1)
{
black_count++;
if(black_count == 5)
{
JOptionPane.showMessageDialog(this, "黑棋胜利");
Clear_Chess();
return;
}
}
else
{
black_count = 0;
}
if(chess[j][i] == 2)
{
white_count++;
if(white_count == 5)
{
JOptionPane.showMessageDialog(this, "白棋胜利");
Clear_Chess();
return;
}
}
else
{
white_count = 0;
}
}
}
for(i = 0;i 7;i++)//左向右斜判断
{
for(int j = 0;j 7;j++)
{
for(int k = 0;k 5;k++)
{
if(chess[i + k][j + k] == 1)
{
black_count++;
if(black_count == 5)
{
JOptionPane.showMessageDialog(this, "黑棋胜利");
Clear_Chess();
return;
}
}
else
{
black_count = 0;
}
if(chess[i + k][j + k] == 2)
{
white_count++;
if(white_count == 5)
{
JOptionPane.showMessageDialog(this, "白棋胜利");
Clear_Chess();
return;
}
}
else
{
white_count = 0;
}
}
}
}
for(i = 4;i 11;i++)//右向左斜判断
{
for(int j = 6;j = 0;j--)
{
for(int k = 0;k 5;k++)
{
if(chess[i - k][j + k] == 1)
{
black_count++;
if(black_count == 5)
{
JOptionPane.showMessageDialog(this, "黑棋胜利");
Clear_Chess();
return;
}
}
else
{
black_count = 0;
}
if(chess[i - k][j + k] == 2)
{
white_count++;
if(white_count == 5)
{
JOptionPane.showMessageDialog(this, "白棋胜利");
Clear_Chess();
return;
}
}
else
{
white_count = 0;
}
}
}
}
}
void Clear_Chess()
{
for(int i=0;i11;i++)
{
for(int j=0;j11;j++)
{
chess[i][j]=0;
}
}
repaint();
}
public void paint(Graphics g)
{
Drawline(g);
Drawchess(g);
}
public void mouseExited(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
}
class myframe extends Frame implements WindowListener
{
mypanel panel;
myframe()
{
setLayout(null);
panel = new mypanel();
add(panel);
panel.setBounds(0,23, 360, 360);
setTitle("单人版五子棋");
setBounds(200, 200, 360, 383);
setVisible(true);
addWindowListener(this);
}
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
public void windowDeactivated(WindowEvent e){}
public void windowActivated(WindowEvent e){}
public void windowOpened(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
}
public class mywindow
{
public static void main(String argc [])
{
myframe f = new myframe();
}
}