五子棋总结

五子棋总结:
首先定义下棋的基本信息:棋盘的行数和列数,棋子的大小,棋盘的大小。由于这些信息是不变的,
而且为了改变信息时的方便,把这些信息定义在接口中。
public interface Config {
public static final int x0=25; //棋盘的开始点
public static final int y0=25;
public static final int ROWS=15; //棋盘的行数
public static final int COLUMNS=15; //棋盘的列数
public static final int Chess_Size=35; //棋子的大小
public static final int Size=40; //棋盘每一格的大小
}
然后建立窗体,在窗体上画棋盘。
1 在窗体上加一个面板
ChessTable ct=new ChessTable();
ct.setBackground(Color.yellow ); //设置面板颜色
ct.setPreferredSize(new Dimension(600,600)); //设置面板大小
this.add(ct); //将面板加到窗体上
....
Graphics g=ct.getGraphics();//在面板上获取画布
for(int i=0;i<Config.ROWS;i++){
g.drawLine(Config.x0+i*Config.Size,Config.y0,
Config.x0+i*Config.Size,Config.y0+(Config.ROWS-1)*Config.Size);
} //画竖向直线
for(int i=0;i<Config.COLUMNS;i++){
g.drawLin(Config.x0,Config.y0+i*Config.Size,
Config.x0+(Config.COLUMNS-1)*Config.Size,Config.y0+i*Config.Size);
} //画横向直线

当窗体显示时看不见棋盘
原因:窗体在显示时会进行重绘。
将画棋盘的方法加到重绘的方法中:
public void paint(Graphics g){
super.paint(g);
for(int i=0;i<Config.ROWS;i++){
g.drawLine(Config.x0+i*Config.Size,Config.y0,
Config.x0+i*Config.Size,Config.y0+(Config.ROWS-1)*Config.Size);
} //画竖向直线
for(int i=0;i<Config.COLUMNS;i++){
g.drawLin(Config.x0,Config.y0+i*Config.Size,
Config.x0+(Config.COLUMNS-1)*Config.Size,Config.y0+i*Config.Size);
} //画横向直线
}
再显示窗体时棋盘会出现

然后是画棋子

人人对战:
黑白交替并且下过棋的地方不能下棋,而且棋要下在交点上
定义一个标记数组public chess[][]=new chess[15][15];

然后给棋盘面板加鼠标监听器
Mouselistener l=new Mouselistener(chess,g,ct);
ct.addMouseListener(l);
...
public Mouselistener(int chess[][],Graphics g,ChessTable ct){
this.chess=chess;
this.g=g;
this.ct=ct;
}
public void mouseClicked(MouseEvent e){
x1=e.getX();
y1=e.getY();
x2=(x1-Config.x0)/Config.Size;
y2=(y1-Config.y0)/Config.Size;
if(chess[x2][y2]==0){ //chess【】【】=0时表示此处没下过棋
if(count==0){ //count=0表示下黑棋
g.setColor(Color.black)
g.fillOval(Config.x0+Config.Size*x2-Config.Size/2,
Config.y0+Config.Size*y2-Config.Size/2, Config.Chess_Size,
Config.Chess_Size); //棋下在交点上
chess[x2][y2]=1;
count++;
}else if(count==1){
g.setColor(Color.white)
g.fillOval(Config.x0+Config.Size*x2-Config.Size/2,
Config.y0+Config.Size*y2-Config.Size/2, Config.Chess_Size,
Config.Chess_Size);
chess[x2][y2]=2;
count--;
}
}
重绘棋子
public void drawchess(Graphics g){
for(int i=0;i<chess.length;i++){
for(int j=0;j<chess[i].length;j++){
if(chess[i][j]==1){
g.setColor(Color.black);
g.fillOval(Config.x0+i*Config.Size-Config.Size/2,
Config.y0+j*Config.Size-Config.Size/2,
Config.Chess_Size, Config.Chess_Size);
}else if(chess[i][j]==2){
g.setColor(Color.white);
g.fillOval(Config.x0+i*Config.Size-Config.Size/2,
Config.y0+j*Config.Size-Config.Size/2,
Config.Chess_Size, Config.Chess_Size);
}
}
}
}
判断输赢:
下一颗棋子,就要在它的四个方向进行判断(水平,竖直,左斜,右斜),当有5个或5个以上的相同颜色的棋子相连时,一方获胜。
public class Win(){
int chess[][];
public Win(int chess[][]){
this.chess=chess;
}
public boolean check(int x,int y){
boolean state=false;
if(checkrow(x,y)||checkcolumn(x,y)||checkleft(x,y)||checkright(x,y)){
state=true;
}
return state;
}
//判断行
public boolean checkrow(int x,int y){
int count=1;
for(int i=x+1;i<chess.length;i++){
if(chess[i][y]==chess[x][y]){
count++;
}else break;
}
for(int i=x-1;i>=0;i--){
if(chess[i][y]==chess[x][y]){
count++;
}else break;
}
if(count>=5){
return true;
}else return false;
}
//判断列
public boolean checkcolumn(int x,int y){
int count=1;
for(int i=y+1;i<chess.length;i++){
if(chess[x][i]==chess[x][y]){
count++;
}else break;
}
for(int i=y-1;i>=0;i--){
if(chess[x][i]==chess[x][y]){
count++;
}else break;
}
if(count>=5){
return true;
}else return false;
}
//判断右斜
public boolean checkright(int x,int y){
int count=1;
for(int i=x+1,j=y+1;i<chess.length&&j<chess.length;i++,j++){
if(chess[i][j]==chess[x][y]){
count++;
}else break;
}
for(int i=x-1,j=y-1;i>=0&&j>=0;i--,j--){
if(chess[i][j]==chess[x][y]){
count++;
}else break;
}
if(count>=5){
return true;
}else return false;
}
//判断左斜
public boolean checkleft(int x,int y){
int count=1;
for(int i=x+1,j=y-1;i<chess.length&&j>=0;i++,j--){
if(chess[i][j]==chess[x][y]){
count++;
}else break;
}
for(int i=x-1,j=y+1;i>=0&&j<chess.length;i--,j++){
if(chess[i][j]==chess[x][y]){
count++;
}else break;
}
if(count>=5){
return true;
}else return false;
}
}
在下棋的时候调用判断输赢的类
if(chess[x2][y2]==0){ //chess【】【】=0时表示此处没下过棋
if(count==0){ //count=0表示下黑棋
g.setColor(Color.black)
g.fillOval(Config.x0+Config.Size*x2-Config.Size/2,
Config.y0+Config.Size*y2-Config.Size/2, Config.Chess_Size,
Config.Chess_Size); //棋下在交点上
chess[x2][y2]=1;
if(win.check()){
javax.swing.JOptionPane.showMessageDialog(null,"黑棋赢了!!!");
}
count++;
}else if(count==1){
g.setColor(Color.white)
g.fillOval(Config.x0+Config.Size*x2-Config.Size/2,
Config.y0+Config.Size*y2-Config.Size/2, Config.Chess_Size,
Config.Chess_Size);
chess[x2][y2]=2;
if(win.check()){
java.swing.JOptionPane.showMessageDialog(null,"白棋赢了!!!");
}
count--;
}
人机对战:
思路:人下一颗棋子,电脑下一颗。而电脑下棋的位置与人下棋子的位置有关,所以考虑到在棋子周围加权值,是电脑下的棋在
权值最大的位置。
首先考虑防守:
定义一个数组用来存放权值。
int com[][]=new int[15][15];
public class defend(){
public Buju(int chess[][], int com[][],int coma[][], Graphics g) {
this.chess = chess;
this.com = com;
this.g = g;
this.coma=coma;
win=new Win(chess);
at=new Attrack(chess,coma,com,g);
}
然后下一颗棋子,就统计一次,根据棋子的布局(即相连的个数)来给它周围的点赋权值。
首先判断棋子相连情况(与判断输赢的方法相同)
// 统计行相连
public void row(int x, int y) {
int count = 1;
int i, j;
int a = 0; //a用来标记棋子周围是否有不同颜色的棋子
for (i = x + 1; i < chess.length; i++) {
if (chess[i][y] == chess[x][y]) {
count++;
} else if (chess[x][y] != chess[i][y] && chess[i][y] != 0) { // 棋子颜色不同且此处有棋子
a++;
break;
} else if (chess[i][y] != chess[x][y]) {
break;
}
}
for (j = x - 1; j > 0; j--) {
if (chess[j][y] == chess[x][y]) {
count++;
} else if (chess[x][y] != chess[j][y] && chess[j][y] != 0) {
a++;
break;
} else if (chess[j][y] != chess[x][y]) {
break;
}
}
com[i][y] = statement(a, count); //赋权值
com[j][y] = statement(a, count); //赋权值
}

// 统计列相连
public void column(int x, int y) {
int count = 1;
int i, j;
int a = 0;
for (i = y + 1; i < chess.length; i++) {
if (chess[x][i] == chess[x][y]) {
count++;
} else if (chess[x][y] != chess[x][i] && chess[x][i] != 0) { // 棋子颜色不同且此处有棋子
a++;
break;
} else if (chess[x][i] != chess[x][y]) {
break;
}
}
for (j = y - 1; j > 0; j--) {
if (chess[x][j] == chess[x][y]) {
count++;
} else if (chess[x][y] != chess[x][j] && chess[x][j] != 0) {
a++;
break;
} else if (chess[x][j] != chess[x][y]) {
break;
}
}
// 加权值
com[x][i] = statement(a, count); //赋权值
com[x][j] = statement(a, count); //赋权值

}

// 统计左斜
public void left(int x, int y) {
int count = 1;
int i, j, k, l;
int a = 0;
for (i = x + 1, j = y - 1; i < chess.length && j >= 0; i++, j--) {
if (chess[i][j] == chess[x][y]) {
count++;
} else if (chess[i][j] != chess[x][y] && chess[i][j] != 0) {
a++;
break;
} else
break;
}
for (k = x - 1, l = y + 1; k >= 0 && l < chess.length; k--, l++) {
if (chess[k][l] == chess[x][y]) {
count++;
} else if (chess[k][l] != chess[x][y] && chess[k][l] != 0) {
a++;
break;
} else
break;
}
com[i][j] = statement(a, count); //赋权值
com[k][l] = statement(a, count); //赋权值
}

public void right(int x, int y) {
int count = 1;
int i, j, k, l;
int a = 0;
for (i = x + 1, j = y + 1; i < chess.length && j < chess.length; i++, j++) {
if (chess[i][j] == chess[x][y]) {
count++;
} else if (chess[i][j] != chess[x][y] && chess[i][j] != 0) {
a++;
break;
} else
break;
}
for (k = x - 1, l = y - 1; k >= 0 && l >= 0; k--, l--) {
if (chess[k][l] == chess[x][y]) {
count++;
} else if (chess[k][l] != chess[x][y] && chess[k][l] != 0) {
a++;
break;
} else
break;
}

com[i][j] = statement(a, count); //赋权值
com[k][l] = statement(a, count); //赋权值
}
根据a和state的值来给棋子赋权值
//返回权值
private int statement(int a, int count) {
if (a == 0 && count == 1) {
return 30;
} else if (a == 1 && count == 1) {
return 10;
} else if (a == 0 && count == 2) {
return 50;
} else if (a == 1 && count == 2) {
return 25;
} else if (a == 0 && count == 3) {
return 100;
} else if (a == 1 && count == 3) {
return 40;
} else if (a == 0 && count == 4) {
return 500;
} else if (a == 1 && count == 4) {
return 500;
}
return 0;
}
赋完权值后,遍历整个棋盘,将电脑要下棋子的位置设为最大权值的位置
// 得到最大权值
public int Countmax(int x, int y) {
int max;
row(x, y);
column(x, y);
left(x, y);
right(x, y);
max = com[0][0];
for (int i = 0; i < com.length; i++) { //在数组中找最大权值
for (int j = 0; j < com[i].length; j++) {
if (max < com[i][j]&&chess[i][j]==0) {
max = com[i][j];
}
}
}
return max;
}
输出下完棋子后的二维数组
public void printcom(){
for(int i=0;i<com.length;i++){
for(int j=0;j<com[i].length;j++){
System.out.print(com[i]+"\t");
}
System.out.println("");
}
System.out.println("*********************************");
}
电脑下棋的方法:
public void printchess(int x,int y,Graphics g){
//调用Countmax方法,找出二维数组中权值最大的点
int count =Countmax(x,y,g);
for(int i=0;i<com.length;i++){
for(int j=0;j<com[i].length;j++){
if(count==com[i][j]&&chess[i][j]==0){
g.setColor(Color.white);
g.fillOval(i*Config.Size+Config.x0-Config.Size/2,
j*Config.Size+Config.y0-Config.Size/2,
Config.Chess_Size, Config.Chess_Size);
chess[i][j]=2;
if(win.check(i,j)){
java.swing.JOptionPane.showMessageDialog(null,"白棋赢了!!!");
}

return 0;
}
}
}
return 0;
}
}
电脑进攻:
public void printchess(int x,int y,Graphics g){
//调用Countmax方法,找出二维数组中权值最大的点
int count =Countmax(x,y,g);
for(int i=0;i<com.length;i++){
for(int j=0;j<com[i].length;j++){
if(count==com[i][j]&&chess[i][j]==0){
g.setColor(Color.white);
g.fillOval(i*Config.Size+Config.x0-Config.Size/2,
j*Config.Size+Config.y0-Config.Size/2,
Config.Chess_Size, Config.Chess_Size);
chess[i][j]=2;
Countmax(i,j); //人下完棋后马上给电脑下棋位置的周围赋权值
if(win.check(i,j)){
java.swing.JOptionPane.showMessageDialog(null,"白棋赢了!!!");
}

return 0;
}
}
}
return 0;
}
}
进攻和防守的权值放在一个数组中保存,便于比较,哪个权值大,电脑下在哪,但进攻和防守的权值相同,不便于使电脑下棋偏于进攻或防守。
基本的五子棋完成,目前的五子棋还是最基本的,还有待优化。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值