[javascript]js的五子棋让红蓝双方自己跟自己下棋

时间:2024-11-20 22:53:27

运行效果(这是未分出胜负):

 

 这是分出胜负:

 

 源代码,把下边的代码放到1.html,然后用浏览器打开,就可以,然后刷新网页:

<!DOCTYPE html>
<html>
    <body>
        <h3>AI五子棋游戏,这个程序有个非常大的Bug,你找到了吗?doge</h3>
        <canvas id="chess" width="450px" height="450px"></canvas>
        <script>
            var chressBord = []; //棋盘当前落子后的记录,是否已经落子,是哪方落子		
            var wins = [];  //存放所有5个棋子在一条线上所有可能性,第一维存放y, 第二维存放x,第三维存放当前的可能性编号
            var count = 0; //赢法总数量
            var blueWin = []; //我们赢法的统计数组
            var redWin = []; //计算机赢法的统计数组
            var chess = document.getElementById("chess");
            var context = chess.getContext('2d');
			var x = 0;
			var y = 0;
 
            for(var i = 0; i < 15; i++)
			{
                chressBord[i] = [];
                wins[i] = [];
                for(var j = 0; j < 15; j++)
				{
                    chressBord[i][j] = 0;
                    wins[i][j] = [];
                }
            }
			
            //横线赢法
            for(var i = 0; i < 15; i++)
                for(var j = 0; j < 11; j++,count++)
                    for(var k = 0; k < 5; k++)
                        wins[i][j+k][count] = true;
			
            //竖线赢法
            for(var i = 0; i < 15; i++)
                for(var j = 0; j < 11; j++,count++)
                    for(var k = 0; k < 5; k++)
                        wins[j+k][i][count] = true;
			
            //正斜线赢法
            for(var i = 0; i < 11; i++)
                for(var j = 0; j < 11; j++,count++)
                    for(var k = 0; k < 5; k++)
                        wins[i+k][j+k][count] = true;
			
            //反斜线赢法
            for(var i = 0; i < 11; i++)  
                for(var j = 14; j > 3; j--,count++)
                    for(var k = 0; k < 5; k++)
                        wins[i+k][j-k][count] = true;
			
            for(var i = 0; i < count; i++)
			{
                blueWin[i] = 0; //这个数组很精髓,记录下棋后每一个位置在每种赢法的得分
                redWin[i] = 0;
            }
						
			//程序运行入口
			function main() 
			{				
				var role = "red";//两个下棋的角色不断切换
				x = Math.floor(Math.random() * 15);	//第一步随机x,y				
				y = Math.floor(Math.random() * 15);	
										
				for (i = 0; i < 225; i++)
				{					
					if(chressBord[x][y] == 0) //computerAI计算后的x,y坐标还没有落子
					{	
						if (role == "red")
						{
							Move(x,y,role); //落子
							chressBord[x][y] = 1; //red玩家棋盘位置占位
							CheckWin(x,y,role, redWin);  //计算落子后是否获胜,这里也很精髓,递归思想
						}
						else
						{
							Move(x,y,role); //落子
							chressBord[x][y] = 2; //blue玩家棋盘位置占位
							CheckWin(x,y,role, blueWin);  //计算落子后是否获胜,这里也很精髓,递归思想
						}
						
						role = (role == "blue") ? "red" : "blue"; //落子后切换角色
					}
					computerAI(); //计算下一步落子的x,y坐标
				}
			}
			
            // 计算机下棋,找玩家最容易赢的位置或者电脑最容易赢的位置
            function computerAI()
			{
                var palyer1Score = []; //这两个数组存放的内容会不断变化,随着计算双方相互切换
                var palyer2Score = [];
                var max = 0;
                var u = 0, v = 0;
                for(var i = 0; i < 15; i++)
				{
                    palyer1Score[i] = [];
                    palyer2Score[i] = [];
                    for(var j = 0; j < 15; j++)
					{
                        palyer1Score[i][j] = 0;
                        palyer2Score[i][j] = 0;
                    }
                }
				
				//找落子赢的概率最大坐标
                for(var i = 0; i < 15; i++)
				{
                    for(var j = 0; j < 15; j++)
					{						
						for(var k = 0; k < count; k++) //遍历到i,j这个坐标时,计算谁的得分更高
						{
							if(chressBord[i][j] != 0 || !wins[i][j][k]) //当前i,j坐标还没落子
								continue;
							
							switch(blueWin[k])
							{
								case 1: palyer1Score[i][j] += 200; break;
								case 2: palyer1Score[i][j] += 400; break;
								case 3: palyer1Score[i][j] += 2000; break;
								case 4: palyer1Score[i][j] += 10000; break;
							}
							
							switch(redWin[k])
							{
								case 1: palyer2Score[i][j] += 220; break;
								case 2: palyer2Score[i][j] += 420; break;
								case 3: palyer2Score[i][j] += 2100; break;
								case 4: palyer2Score[i][j] += 20000; break;
							}
						}
						
						if(palyer1Score[i][j] > max) //如果玩家落子的分数多,就替换
						{
							max  = palyer1Score[i][j];
							u = i;
							v = j;
						}
						else if(palyer1Score[i][j] == max)  //如果玩家落子的分数跟原来最多分数一样多
						{
							if(palyer2Score[i][j] > palyer2Score[u][v]) //如果电脑在i,j落子的分数比u,v的分数多,就替换
							{
								u = i;
								v = j;    
							}
						}
						
						if(palyer2Score[i][j] > max) //如果电脑下棋新位置分数比原来的多,就替换
						{
							max  = palyer2Score[i][j];
							u = i;
							v = j;
						}
						else if(palyer2Score[i][j] == max) //如果电脑下棋新位置分数跟原来的一样多
						{
							if(palyer1Score[i][j] > palyer1Score[u][v]) //如果玩家落子的分数多,就准备把玩家最好的位置占掉
							{
								u = i;
								v = j;    
							}
						}
                    }
                }
				x = u;
				y = v;
            }
			            
            function Move(i,j,Role) //落子
			{
                context.beginPath();
                context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);// 画圆
                context.closePath();    
                context.fillStyle = Role;
                context.fill(); //填充颜色				
            }
			
			function CheckWin(i, j, Role, WinArray)
			{			
				for(var k = 0; k < count; k++)
					if(wins[i][j][k]) // 将可能赢的情况都加1
					{
						WinArray[k]++; //第k这个位置要注意,每一个k代表一种赢的可能性,并且前边的x,y代表第K种赢法x,y的坐标对,这个对于理解算法是否赢很重要
						if(WinArray[k] >= 5)
						{
							alert(Role + ': 恭喜,你赢了!')
							throw new Error(Role + " player win!!");;
						}
					}
			}			
            
            function drawChessBoard()
			{
                for(var i = 0; i < 15; i++)
				{
                    context.moveTo(15 + i * 30 , 15);
                    context.lineTo(15 + i * 30 , 435);
                    context.moveTo(15 , 15 + i * 30);
                    context.lineTo(435 , 15 + i * 30);
                    context.stroke();
                }
            }
			
            drawChessBoard(); // 画棋盘
			main();
        </script>
    </body>
</html>

import javax.swing.*;
import java.awt.*;
import java.util.Scanner;

public class FiveInOneLine extends JFrame {
    private final Image buffer;  // 双缓冲图像
    private final Graphics bufferGraphics;  // 双缓冲图像的绘图上下文
    int[][] chessBoard;
    int[][][] wins;
    int count;
    int[] blueWin;
    int[] redWin;
    int x, y;

    FiveInOneLine()
    {
        setLayout(null);
        setSize(700, 900);
        setLocationRelativeTo(null);
        setVisible(true);
        buffer = createImage(700, 900);
        bufferGraphics = buffer.getGraphics();
        chessBoard = new int[15][15];
        wins = new int[15][15][573];
        blueWin = new int[573];
        redWin = new int[573];

        drawchessBoard();
        generateWinArray();
        main2();
    }

    void generateWinArray()
    {
        //横线赢法
        for(int i = 0; i < 15; i++)
            for(int j = 0; j < 11; j++,count++)
                for(int k = 0; k < 5; k++)
                    wins[i][j+k][count] = 1;

        //竖线赢法
        for(int i = 0; i < 15; i++)
            for(int j = 0; j < 11; j++,count++)
                for(int k = 0; k < 5; k++)
                    wins[j+k][i][count] = 1;

        //正斜线赢法
        for(int i = 0; i < 11; i++)
            for(int j = 0; j < 11; j++,count++)
                for(int k = 0; k < 5; k++)
                    wins[i+k][j+k][count] = 1;

        //反斜线赢法
        for(int i = 0; i < 11; i++)
            for(int j = 14; j > 3; j--,count++)
                for(int k = 0; k < 5; k++)
                    wins[i+k][j-k][count] = 1;
    }

    void main2()
    {
        String role = "red";//两个下棋的角色不断切换
        x = (int) Math.floor(Math.random() * 15);	//第一步随机x,y
        y = (int) Math.floor(Math.random() * 15);

        for (int i = 0; i < 225; i++)
        {
            if(chessBoard[x][y] == 0) //computerAI计算后的x,y坐标还没有落子
            {
                if (role.equals("red"))
                {
                    drawChess(x,y,new Color(255,0,0)); //落子
                    chessBoard[x][y] = 1; //red玩家棋盘位置占位
                    CheckWin(x,y,role, redWin);  //计算落子后是否获胜,这里也很精髓,递归思想
                }
                else
                {
                    drawChess(x,y,new Color(0,0,255)); //落子
                    chessBoard[x][y] = 2; //blue玩家棋盘位置占位
                    CheckWin(x,y,role, blueWin);  //计算落子后是否获胜,这里也很精髓,递归思想
                }

                role = (role.equals("blue")) ? "red" : "blue"; //落子后切换角色
            }

            computerAI(); //计算下一步落子的x,y坐标
            System.out.println("new x: " + x + ", y: " + y);
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    void computerAI()
    {
        int[][] palyer1Score = new int[15][15]; //这两个数组存放的内容会不断变化,随着计算双方相互切换
        int[][] palyer2Score = new int[15][15];
        int max = 0;
        int u = 0, v = 0;

        //找落子赢的概率最大坐标
        for(int i = 0; i < 15; i++)
        {
            for(int j = 0; j < 15; j++)
            {
                for(int k = 0; k < count; k++) //遍历到i,j这个坐标时,计算谁的得分更高
                {
                    if(chessBoard[i][j] != 0 || 0 == wins[i][j][k]) //当前i,j坐标还没落子
                        continue;

                    switch(blueWin[k])
                    {
                        case 1: palyer1Score[i][j] += 200; break;
                        case 2: palyer1Score[i][j] += 400; break;
                        case 3: palyer1Score[i][j] += 2000; break;
                        case 4: palyer1Score[i][j] += 10000; break;
                    }

                    switch(redWin[k])
                    {
                        case 1: palyer2Score[i][j] += 220; break;
                        case 2: palyer2Score[i][j] += 420; break;
                        case 3: palyer2Score[i][j] += 2100; break;
                        case 4: palyer2Score[i][j] += 20000; break;
                    }
                }

                if(palyer1Score[i][j] > max) //如果玩家落子的分数多,就替换
                {
                    max  = palyer1Score[i][j];
                    u = i;
                    v = j;
                }
                else if(palyer1Score[i][j] == max)  //如果玩家落子的分数跟原来最多分数一样多
                {
                    if(palyer2Score[i][j] > palyer2Score[u][v]) //如果电脑在i,j落子的分数比u,v的分数多,就替换
                    {
                        u = i;
                        v = j;
                    }
                }

                if(palyer2Score[i][j] > max) //如果电脑下棋新位置分数比原来的多,就替换
                {
                    max  = palyer2Score[i][j];
                    u = i;
                    v = j;
                }
                else if(palyer2Score[i][j] == max) //如果电脑下棋新位置分数跟原来的一样多
                {
                    if(palyer1Score[i][j] > palyer1Score[u][v]) //如果玩家落子的分数多,就准备把玩家最好的位置占掉
                    {
                        u = i;
                        v = j;
                    }
                }
            }
        }
        x = u;
        y = v;
    }

    void CheckWin(int i, int j, String Role, int[] WinArray)
    {
        for(int k = 0; k < count; k++)
            if(wins[i][j][k] == 1) // 将可能赢的情况都加1
            {
                WinArray[k]++; //第k这个位置要注意,每一个k代表一种赢的可能性,并且前边的x,y代表第K种赢法x,y的坐标对,这个对于理解算法是否赢很重要
                if(WinArray[k] >= 5)
                {
                    System.out.println(Role + " player win!!");
                    new Scanner(System.in).hasNextInt();
                }
            }
    }

    void drawChess(int mouse_x, int mouse_y, Color c)
    {
        mouse_x = 15 + mouse_x * 30; //把一个区域的点击放到一个点
        mouse_y = 15 + mouse_y * 30;
        bufferGraphics.setColor(c);
        bufferGraphics.fillArc(mouse_x - 12, mouse_y - 38, 20, 20, 0, 360);
        getContentPane().getGraphics().drawImage(buffer, 0, 0, null);
    }

    void drawchessBoard()
    {
        for (int i = 0; i < 15; i++)
        {
            bufferGraphics.drawLine(15 + i * 30, 15, 15 + i * 30, 435);
            bufferGraphics.drawLine(15, 15 + i * 30, 435, 15 + i * 30);
        }
    }
 
    public static void main(String[] args) {   //这个程序有个非常大的Bug,你找到了吗?
        new FiveInOneLine();
    }
}