Java五⼦棋项⽬学习思路记录
在同学的指点下,打算做个Java五⼦棋项⽬练⼿。
参照
此篇原创⽂章和代码学习实现Java五⼦棋⼩项⽬。记录⼀些学习⼼得。
⽆Java经验和基础⼩⽩,看了清华⼤学出版社陈国军主编的《Java程序设计基础(第5版)》学习之后,基本对Java有个概念,个⼊门项⽬加深理解,学会应⽤。
话说CSDN也是第⼀次学着使⽤,怎么插⼊代码呢……
package Charlie.demo;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit; //抽象类,获得屏幕的长度和⾼度的⽅法包含在内
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class FiveGame extends JFrame
{
//设置游戏界⾯
/* 屏幕分辨率求法:
int w = f.getToolkit().getScreenSize().width;//宽度
int h = f.getToolkit().getScreenSize().height;//⾼度
都是⽤来获取屏幕的宽⾼,
this.setLocation((width - 500) / 2 , (height - 500) / 2 );
这是使你的窗⼝能够居中显⽰,这样看起来美观。
*/
int width = DefaultToolkit().getScreenSize().width;
int height = DefaultToolkit().getScreenSize().height;
int allChess[][]=new int[15][15]; // ⽤数组来保存棋⼦,0表⽰⽆⼦,1表⽰⿊⼦,2表⽰⽩⼦。15⾏,15列的数组
boolean isblack = true;//⽤来表⽰⿊⼦还是⽩⼦, true表⽰⿊⼦ false表⽰⽩⼦
boolean canPlay = true;// ⽤来表⽰当前游戏是否结束
String message = "⿊⽅先⾏";
String blackMessage = "⽆限制";
String whiteMessage = "⽆限制";
public FiveGame() //FI类的构造⽅法
{
this.setTitle("五⼦棋1.0"); //在构造⽅法内调⽤另⼀个构造⽅法,this关键字必须写在构造⽅法内的第⼀⾏位置
this.setSize(500,500);
this.setLocation((width - 500) / 2 , (height - 500) / 2 );//设置组件显⽰位置的左上⾓坐标(x,y)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//Java窗⼝的关闭按钮,结束程序
this.setResizable(false); //设置窗⼝不可改变,固定窗⼝⼤⼩
this.setVisible(true);//设置组件是否显⽰
//它会直接调⽤下⾯的⽅法对界⾯进⾏重⾏绘画
}//画棋盘界⾯
public void paint(Graphics g)
{
//双缓冲技术
BufferedImage buf = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
// 这个bufferedImage 可以在⽹上查相关⽤法,它是对图像的⼀种处理。
/*
java.awt.image.BufferedImage是带数据缓冲区的图像类,BuferedImage⽣成的图⽚在内存⾥有⼀个图像缓冲区,
利⽤这个缓冲区我们可以很⽅便的操作这个图⽚,通常⽤来做图⽚修改操作,如:⼤⼩变换、图⽚变灰、设置图⽚
透不透明等。
Graphics g1 = ateGraphics(); // 创建画笔
g1.setColor(new Color(0,169,158));
g1.fill3DRect(43, 60, 375, 375, true);//在窗⼝中画出⼀个棋盘
/*
fill3DRect(int x,int y,int width,int height,boolean rasied):⽤预定的颜⾊填充⼀个突出显⽰的矩形。
x,y是矩形的左上⾓位置,参数width和height是矩形的宽和⾼,参数raised是突出与否。
*/
for (int i = 0; i <= 15; i++) {
g1.setColor(Color.WHITE);
g1.drawLine(43, 60+i*25, 375+43, 60+i*25); //画棋盘横线,15*15的⽅格棋盘
g1.drawLine(43+i*25, 60, 43+i*25, 375+60); //画棋盘竖线
}
g1.setFont(new Font("⿊体",Font.BOLD,20));
g1.drawString("游戏信息:"+message,50,50); //以当前的颜⾊和字体,(x,y)为左下⾓,绘制字符串str
g1.drawRect(30, 440, 180, 40);
g1.drawRect(250, 440, 180, 40); //画⿊⽅时间与⽩⽅时间字符串的边框
g1.setFont(new Font("宋体",0,12));
g1.drawString("⿊⽅时间: "+blackMessage,40,465);
g1.drawString("⽩⽅时间: "+whiteMessage,260,465);
g1.drawRect(430,66,55,20);
g1.drawString("重新开始",432,80); //重新开始按钮
g1.drawRect(430,106,55,20);
g1.drawString("游戏设置",432,120); //游戏设置按钮
g1.drawRect(430,146, 55, 20);
g1.drawString("游戏说明", 432, 160); // 游戏说明按钮
g1.drawRect(430, 186, 55, 20);
g1.drawString("退出游戏", 432, 200); // 退出游戏按钮
g1.drawRect(430, 246, 55, 20);小白学java有前途吗
g1.drawString("悔棋", 442, 260); // 悔棋
g1.drawRect(430, 286, 55, 20);
g1.drawString("认输", 442, 300); // 认输
g.drawImage(buf, 0, 0,this);
/*
public abstract boolean drawImage(Image img,int x,int y,ImageObserver observer)
显⽰图像⽂件img,左上⾓在(x,y)点。其中observer是⽤于监听图像创建进度的对象。
*/
public void mousePressed(MouseEvent e){
if(canPlay){
X();
Y(); // ⽤来获取⿏标坐标
if(x>55 && x<= 405 && y>=72 && y<=420) //(55,72),(405,422)分别是左上⾓圆⼼和右下⾓圆⼼坐标
{
//让⿏标在棋盘范围内
if((x-55)%25>12)//取余数,余数是超出整数格的距离。这⼀步判断⿏标位置超出整数格多少,每半格的距离是12.5 {
x=(x-55)/25 + 1;//⼤于半格距离的,在下⼀格落⼦。此时x由横坐标变为格⼦序号
}
else
{
x = (x-55)/25;//⼩于半格的,在本格落⼦。
}
if((y-72)%25>12)
{
y=(y-72)/25 + 1;
else
{
y=(y-72)/25;
}
/
** (405-55)/25=14格⽽棋盘是15*15所以这⾥需要进⾏⼀个判断 12可以进⾏改动
不能超过14就⾏。
这⾥⽤的是整形变量,精确度不准,容易造成所点的区域下不了棋
2.0版本会升级到把棋⼦放在交点上,不会在⽅格内下
*/
//落⼦
/** x,y代表棋⼦的位置所在
chessX,chessY⽤来记录下棋的位置以便悔棋时需要
如 chessX[0] = 3;
chessY[0] = 4;
即第⼀步棋⼦下在(3,4)位置
*/
if(allChess[x][y] == 0)//如果⽆⼦
{
chessX[countX++] = x;
chessY[countY++] = y;
if(isblack)//如果是⿊⼦
{
allChess[x][y] = 1;//该数组位置保存⿊棋
isblack = false;//改变变量,轮到⽩棋落⼦
message = "⽩⽅下⼦";
}
else
{
allChess[x][y] = 2;
isblack = true;
message = "⿊⽅下⼦";
}
//调⽤⽅法进⾏绘制,如果allChess[x][y] = 1; 则画出⿊棋
// 下⼀个棋就进⾏输赢判断
if(this.isWin()){
if(allChess[x][y] == 1){
JOptionPane.showMessageDialog(this, "游戏结束,⿊⽅胜利");
}else {
JOptionPane.showMessageDialog(this, "游戏结束,⽩⽅胜利");
}
this.canPlay = false; //表⽰游戏结束
}
}
}
}
for(int i=0; i<15; i++){ //数组声明时是⾏与列的数⽬,但实际数组是从0开始标记的。
for (int j = 0; j < 15; j++) {
/
/画实⼼⿊⼦
if(allChess[i][j] == 1){
int tempX = i*25+47;
int tempY = j*25+64;
/*
格⼦边长25,棋⼦直径16,相差9,⼀半是4.5,但因为是整型,取4。(43+4,60+4)是左上⾓棋⼦相切矩形的
左上⾓坐标
*/
g1.setColor(Color.BLACK);
g1.fillOval(tempX, tempY, 16, 16);
/*
Graphics类的常⽤⽅法
public abstract void fillOval(int x,int y,int width,int height)
在指定的矩形区域内画⼀个椭圆,并⽤当前颜⾊进⾏填充
*/
g1.setColor(Color.BLACK);
g1.drawOval(tempX, tempY, 16, 16);
/*
Graphics类的常⽤⽅法
public abstract void drawOval(int x,int y,int width,int height)
在指定的矩形区域内画⼀个椭圆
*/
}
//画实⼼⽩⼦
if(allChess[i][j] == 2){
int tempX = i*25+47;
int tempY = j*25+64;
g1.setColor(Color.WHITE);
g1.fillOval(tempX, tempY, 16, 16);
g1.setColor(Color.WHITE);
g1.drawOval(tempX, tempY, 16, 16);
}
}
}
/*
allChess[i][j]是你下棋的位置,对这个数组进⾏判断。如果为1,那就代表是⿊棋,2就是⽩棋。 tempX,tempY 是⽤来确定棋⼦所在的位置区域的顶点坐标。
因为⼀个⽅格是25*25的⼤⼩,所以我们定义⼀个16*16⽅格的内切圆,并涂上相应的颜⾊。
这样就达到我们在棋盘上的地⽅进⾏下棋的⽬的。
*/
/**
* 判断输赢规则
* @return
*/
public boolean isWin(){
boolean flag = false;
int count = 1; //⽤来保存共有相同颜⾊多少棋⼦相连,初始值为1
int color = allChess[x][y]; //color = 1 (⿊⼦) color = 2(⽩⼦)
//判断横向是否有5个棋⼦相连,特点:纵坐标是相同,即allChess[x][y] 中y值是相同
count = this.checkCount(1,0,color);
if(count >= 5)
{
flag = true;
}
else
{
/
/判断纵向
count = this.checkCount(0,1,color);
if(count >= 5)
{
flag = true;
}
else
{
//判断右上,左下
count = this.checkCount(1,-1,color);
if(count >= 5)
{
flag = true;
}
else
{
//判断右下,左上
count = this.checkCount(1,1,color);
if(count >= 5)
{
flag = true;
}
}
}
}
return flag;
}
/**
* 检查棋盘中的五⼦棋是否连城五⼦
* @param xChange
* @param yChenge
* @param color
* @return
*/
public int checkCount(int xChange , int yChenge ,int color){
int count = 1;
int tempX = xChange; //xChange、yChenge的值由调⽤语句传值⽽来。xChanege即是x的变化量 int tempy = yChenge; //保存初始值,tempX和tempY为局部变量
//全局变量x,y最初为⿏标点击的坐标,
//经下棋⽅法已经将x,y的范围变成0-15(遍历整个棋盘,寻相同颜⾊的棋⼦)
while(x + xChange >=0 && x+xChange <15 && y+yChenge >=0 &&
y+yChenge < 15 && color == allChess[x+xChange][y+yChenge]){
// allChess[x+xChange][y+yChenge] 表⽰移动⼀个坐标来进⾏判断是否为同⼀颜⾊
//例如横向判断checkCount(1,0,color); 传⼊xchange = 1,ychange = 0;
// 即每次向右移动⼀次,如果满⾜同⼀颜⾊就继续判断,不满⾜则返回
count++;
if(xChange != 0) xChange++; // 满⾜条件继续向右判断
if(yChenge != 0 ){ // 横向判断ychange = 0 不满⾜条件不执⾏
if(yChenge != 0){
if(yChenge > 0) {
yChenge++; //使棋⼦沿着右下⼀条线移动,进⾏判断
}else {
yChenge--; // 使棋⼦沿着右上⼀条线移动,进⾏判断
}
}
}
}
// 经过以上判断 xchange和ychange可能发⽣改变,所以最开始设置初始值以便接下来使⽤
xChange = tempX;
yChenge = tempy; // 恢复初始值
//以棋⼦为中⼼,横向判断为例,分为两个⽅向,上⾯是右边判断,下⾯是进⾏左边
while(x-xChange >=0 && x-xChange <15 && y-yChenge >=0 &&
y-yChenge <15 && color == allChess[x-xChange][y-yChenge]){
//(x-xChange >=0 && x-xChange <15 && y-yChenge >=0 &&
// y-yChenge <15) 始终保持棋⼦在移动时保持在规定的区域内
count++;
if(xChange != 0){
xChange++;
}
if(yChenge != 0){
if (yChenge > 0) {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论