1. 程式人生 > >java實現一個簡單的五子棋遊戲

java實現一個簡單的五子棋遊戲

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();}}}}}