java實現一個簡單的五子棋遊戲
阿新 • • 發佈:2018-12-22
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class ChessFrame extends JFrame implements MouseListener,Runnable{
/**
*
*/
private static final long serialVersionUID = 1L;
//取得螢幕的寬度和高度
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
//背景圖片
BufferedImage bgImage = null;
//儲存棋子的座標
int x = 0;
int y = 0;
//儲存之前下過的全部棋子的座標 陣列中預設初始值為0,代表沒有棋子 1代表黑子 2代表 白子
int[][] allChess = new int[19][19];
//標識當前是黑棋還是白棋
boolean isBack = true;
int i,j;
//標識當前遊戲是否可以繼續
boolean canPlay = true;
//顯示的提示資訊
String message = "黑方先行";
//點選開始遊戲之後才可以進行操作棋盤
boolean start = false;
//儲存最多擁有多少時間
int maxTime = 0;
//做倒計時的執行緒類
Thread t = new Thread(this);
//儲存黑方和白方的剩餘時間
int blackTime = 0;
int whiteTime = 0;
//儲存黑白方剩餘時間的顯示資訊
String blackMessage = "無限制";
String whiteMessage = "無限制";
@SuppressWarnings("deprecation")
public ChessFrame(){
//設定標題
this.setTitle("五子棋");
//設定窗體大小
this.setSize(700, 690);
//設定窗體出現位置
this.setLocation((width-500)/2, (height-500)/2);
//將窗體設定為大小不可改變
this.setResizable(false);
//將窗體的關閉方式設定為預設關閉後程序結束
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//將窗體顯示出來
this.setVisible(true);
//為窗體加入監聽器
this.addMouseListener(this);
//開啟執行緒
t.start();
//執行緒掛起
t.suspend();
//重新整理螢幕,防止遊戲開始時出現無法顯示的情況
this.repaint();
try {
bgImage = ImageIO.read(new File("C:\\Users\\DELL\\workspace\\game\\image\\chess.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void paint(Graphics g) {
// 雙緩衝技術防止螢幕閃爍
BufferedImage bi = new BufferedImage(1024, 1024,BufferedImage.TYPE_INT_RGB);
Graphics g2 = bi.createGraphics();
g2.setColor(Color.BLACK);
//繪製背景
g2.drawImage(bgImage, 0, 0, this);
//輸出標題資訊
g2.setFont(new Font("黑體",Font.BOLD,20));
g2.drawString("遊戲資訊: "+message, 50, 55);
//輸出時間資訊
g2.setFont(new Font("宋體", 0, 14));
g2.drawString("黑方時間:"+blackMessage, 50, 650);
g2.drawString("白方時間:"+whiteMessage, 450, 650);
g2.drawString("開始遊戲", 610, 160);
g2.drawString("遊戲設定", 610, 230);
g2.drawString("遊戲說明", 610, 300);
g2.drawString("認輸", 610, 400);
g2.drawString("關於", 610, 470);
g2.drawString("退出", 610, 540);
//繪製棋盤
for(int i = 0;i < 19;i++){
g2.drawLine(30, 80+i*30, 570, 80+i*30);
g2.drawLine(30+i*30, 80, 30+i*30, 620);
}
//標註點位
g2.fillOval(120, 170, 4, 4);
g2.fillOval(480, 170, 4, 4);
g2.fillOval(120, 530, 4, 4);
g2.fillOval(480, 530, 4, 4);
g2.fillOval(300, 170, 4, 4);
g2.fillOval(120, 350, 4, 4);
g2.fillOval(480, 350, 4, 4);
g2.fillOval(300, 530, 4, 4);
g2.fillOval(300, 350, 4, 4);
/**繪製棋子
* 在下棋時,棋子需要下到棋盤線條的交叉點處
* 此時,需要計算出 滑鼠點選位置的座標 和 離它最近的交叉點座標的位置
* 最近點的座標 = 索引 * 網格的間距 + 距離視窗的邊距
* 最後棋子應該顯示到中心點 則這個最近點的座標需要加減棋子的半徑
* x = ((x+15)/30)*30;
* y = ((y+15)/30)*30;
* g.setColor(Color.WHITE);
* g.fillOval(x-10, y-20, 20, 20);
*/
for(int i = 0; i < 19; i++){
for(int j = 0; j < 19;j++){
//棋子下的位置的位置
int tempX = i * 30 + 30;
int tempY = j * 30 + 90;
//繪製黑子
if(allChess[i][j] == 1){
g2.fillOval(tempX-10,tempY-20, 20, 20);
}
//繪製白子
if(allChess[i][j] == 2){
g2.setColor(Color.WHITE);
g2.fillOval(tempX-10,tempY-20, 20, 20);
g2.setColor(Color.BLACK);
g2.drawOval(tempX-10,tempY-20, 20, 20);
}
}
}
g.drawImage(bi, 0, 0, this);
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@SuppressWarnings("deprecation")
@Override
public void mousePressed(MouseEvent e) { //滑鼠按下時呼叫
// TODO Auto-generated method stub
// System.out.println(e.getX());
// System.out.println(e.getY());
// x = ((x+15)/30)*30;
// y = ((y+15)/30)*30;
// if(e.getX() >= 30 && e.getX() <= 570 && e.getY() >= 80 && e.getY() <= 640){
// JOptionPane.showMessageDialog(this, "請選擇開始遊戲!");
// canPlay = true;
// }
if(canPlay == true && start == true){
//獲取滑鼠點選的座標
x = e.getX();
y = e.getY();
if(x >= 30 && x <= 570 && y >= 80 && y <= 640){
//棋子下的棋盤線條中心位置座標 網格(30)的整數倍
x = ((x+15)/30)*30;
y = ((y+15)/30)*30;
//最後棋子位置的座標轉換為 陣列的索引
i = (x - 30)/30;
j = (y - 80)/30;
//當前位置沒有棋子 二維陣列預設0
if(allChess[i][j] == 0){
if(isBack == true){//二維陣列賦值,1代表黑色
allChess[i][j] = 1;
//改變棋子顏色
isBack = false;
message = "請白方落子";
}else{ //賦值 2 代表白色
allChess[i][j] = 2;
//改變棋子顏色
isBack = true;
message = "請黑方落子";
}
//是否贏得遊戲
boolean flag = this.checkWin();
if(flag == true){
JOptionPane.showMessageDialog(this, "五子連珠,"+(allChess[i][j]==1?"黑方獲勝!":"白方獲勝!"));
//勝利之後,棋盤不允許再進行操作
canPlay = false;
}
}else{
JOptionPane.showMessageDialog(this, "當前位置已經有棋子,請重新落子!");
}
//重新執行一次paint方法
this.repaint();
}
}
//開始遊戲
if(e.getX() >= 610 && e.getX() <= 650 && e.getY() >= 140 && e.getY() <= 170){
int result = JOptionPane.showConfirmDialog(this, "是否重新開始遊戲?");
//重新開始遊戲
if(result == 0){
//清空棋盤 陣列中的資料全部為0
for(int i = 0;i < 19;i++){
for(int j = 0; j < 19;j++){
allChess[i][j] = 0;
}
}
//遊戲資訊的顯示為預設值
message = "黑方先行";
isBack = true;
blackTime = maxTime;
whiteTime = maxTime;
//輸入的設定時間大於0
if(maxTime > 0){
blackMessage = maxTime/3600+":"+(maxTime/60 - maxTime/3600*60)+":"+(maxTime - maxTime /60 * 60);
blackMessage = maxTime/3600+":"+(maxTime/60 - maxTime/3600*60)+":"+(maxTime - maxTime /60 * 60);
//t.resume();
}else{
blackMessage = "無限制";
whiteMessage = "無限制";
}
this.canPlay = true;
//點選開始遊戲以後才可以下棋
start = true;
this.repaint();
}
}
//設定
if(e.getX() >= 610 && e.getX() <= 650 && e.getY() >= 200 && e.getY() <= 230){
String sc = JOptionPane.showInputDialog("請輸入遊戲的最大時間(分鐘),輸入0,表示沒有時間限制:");
try {
//換算為 秒
maxTime = Integer.parseInt(sc) * 60;
//設定時間小於0時
if(maxTime < 0){
JOptionPane.showMessageDialog(this, "請正確輸入資訊!不允許輸入負數!");
}
//設定時間等於0時
if(maxTime == 0){
int result = JOptionPane.showConfirmDialog(this, "是否重新開始遊戲");
//重新開始遊戲
if(result == 0){
//清空棋盤
for(int i = 0;i < 19;i++){
for(int j = 0; j < 19;j++){
allChess[i][j] = 0;
}
}
//恢復預設設定
message = "黑方先行";
isBack = true;
blackMessage = "無限制";
whiteMessage = "無限制";
this.canPlay = true;
start = true;
this.repaint();
}
}
//設定時間大於0
if(maxTime > 0){
int result = JOptionPane.showConfirmDialog(this, "設定完成,是否重新開始遊戲?");
//重新開始遊戲
if(result == 0){
//清空棋盤
for(int i = 0;i < 19;i++){
for(int j = 0; j < 19;j++){
allChess[i][j] = 0;
}
}
//恢復預設設定
message = "黑方先行";
isBack = true;
blackTime = maxTime;
whiteTime = maxTime;
blackMessage = maxTime/3600+":"+(maxTime/60 - maxTime/3600*60)+":"+(maxTime - maxTime /60 * 60);
whiteMessage = maxTime/3600+":"+(maxTime/60 - maxTime/3600*60)+":"+(maxTime - maxTime /60 * 60);
t.resume();
this.canPlay = true;
start = true;
this.repaint();
}
}
} catch (Exception e2) {
JOptionPane.showMessageDialog(this, "請正確輸入資訊!");
}
}
//遊戲說明
if(e.getX() >= 610 && e.getX() <= 650 && e.getY() >= 280 && e.getY() <= 300){
JOptionPane.showMessageDialog(this, "隨便下,開心就好!");
}
//認輸
if(e.getX() >= 610 && e.getX() <= 630 && e.getY() >= 380 && e.getY() <= 410){
int result = JOptionPane.showConfirmDialog(this, "確認認輸?");
if(result == 0){
if(isBack){
JOptionPane.showMessageDialog(this, "黑方認輸,遊戲結束!");
}else{
JOptionPane.showMessageDialog(this, "白方認輸,遊戲結束!");
}
canPlay = false;
}
}
//關於
if(e.getX() >= 610 && e.getX() <= 630 && e.getY() >= 450 && e.getY() <= 480){
JOptionPane.showMessageDialog(this, "隨便做做,請多多指教");
}
//退出
if(e.getX() >= 610 && e.getX() <= 630 && e.getY() >= 520 && e.getY() <= 550){
JOptionPane.showMessageDialog(this, "結束!");
System.exit(0);
}
}
/**
* 判斷遊戲是否結束的方法
* 以當前棋子為中心向各個方向進行查詢,找到五個相同的顏色即為遊戲結束
* */
private boolean checkWin() {
// TODO Auto-generated method stub
boolean flag = false;
//判斷橫向是否有五個棋子是相同的顏色
int count1 = 1;//相同顏色棋子的個數
int color = allChess[i][j]; //剛下的棋子的顏色
int a = 1; //棋子索引的增量
while(color == allChess[i+a][j]){
count1++;
a++;
}
a = 1;
while(color == allChess[i-a][j]){
count1++;
a++;
}
if(count1 >= 5){
flag = true;
}
//判斷縱向是否有五個棋子是相同的顏色
int count2 = 1;
a = 1;
while(color == allChess[i][j+a]){
count2++;
a++;
}
a = 1;
while(color == allChess[i][j-a]){
count2++;
a++;
}
if(count2 >= 5){
flag = true;
}
//右上 左下 是否有五個棋子是相同的顏色
int count3 = 1;
a = 1;
while(color == allChess[i+a][j-a]){
count3++;
a++;
}
a = 1;
while(color == allChess[i-a][j+a]){
count3++;
a++;
}
if(count3 >= 5){
flag = true;
}
//左上 右下 是否有五個棋子是相同的顏色
int count4 = 1;
a = 1;
while(color == allChess[i-a][j-a]){
count4++;
a++;
}
a = 1;
while(color == allChess[i+a][j+a]){
count4++;
a++;
}
if(count4 >= 5){
flag = true;
}
return flag;
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void run() {
// TODO Auto-generated method stub
//判斷是否有時間限制
if(maxTime > 0){
while(true){
//當前是黑棋
if(isBack){
//時間減少
blackTime--;
//當時間到的時候
if(blackTime == 0){
JOptionPane.showMessageDialog(this, "黑方遊戲超時,遊戲結束");
canPlay = false;
return;
}
// blackMessage = blackTime/3600+":"+(blackTime/60 - blackTime/3600*60)+":"+(blackTime - blackTime /60 * 60);
//blackTime = maxTime;
}else{
whiteTime--;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
@SuppressWarnings("unused")
ChessFrame c = new ChessFrame();
}
}
if(whiteTime == 0){JOptionPane.showMessageDialog(this, "白方遊戲超時,遊戲結束");canPlay = false;return;}}blackMessage = blackTime/3600+":"+(blackTime/60 - blackTime/3600*60)+":"+(blackTime - blackTime /60 * 60);whiteMessage = whiteTime/3600+":"+(whiteTime/60 - whiteTime/3600*60)+":"+(whiteTime - whiteTime /60 * 60);this.repaint();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}