zoukankan      html  css  js  c++  java
  • 五子棋算法

    前几天看到的一个比较有意思的算法;然后 实现了一下;最后给它加了一个UI界面;

    核心获胜逻辑如下:

    def __color_continius(self, arr, color):
            """
            判断某一颜色的棋子最大连续个数
            """
            max_count = 1
            _count = 1
            for i in range(0, len(arr) - 1):
                x1, y1 = arr[i]
                x2, y2 = arr[i + 1]
                if self.__pieces[x1][y1] == color and self.__pieces[x2][y2] == color:
                    _count += 1
                else:
                    _count = 1
                if _count >= max_count:
                    max_count = _count
            return max_count
        def __check_win(self, selected_x, selected_y, color):
            """
            判断某一颜色棋子的输赢,以当前棋子为中心,4子为半径判断四个方向即可
            """
            _row = []
            for x in range(selected_x - 4, selected_x + 5):
                if x >= 0 and x < self.__width:
                    _row.append((x, selected_y))
            if self.__color_continius(_row, color) >= 5:
                return True
            _col = []
            for x in range(selected_y - 4, selected_y + 5):
                if x >= 0 and x < self.__height:
                    _col.append((selected_x, x))
            if self.__color_continius(_col, color) >= 5:
                return True
            lb_rt = []
            for x in range(-4, 5):
                s_x = selected_x + x
                s_y = selected_y - x
                if s_x >= 0 and s_x < self.__width and s_y > 0 and s_y < self.__height:
                    lb_rt.append((s_x, s_y))
            if self.__color_continius(lb_rt, color) >= 5:
                return True
            lt_rb = []
            for x in range(-4, 5):
                s_x = selected_x + x
                s_y = selected_y + x
                if s_x >= 0 and s_x < self.__width and s_y > 0 and s_y < self.__height:
                    lt_rb.append((s_x, s_y))
            if self.__color_continius(lt_rb, color) >= 5:
                return True
            return False
    
        def __is_draw(self):
            """
            判断是否是和棋
            """
            is_draw = True
            for x in self.__pieces:
                for y in x:
                    if y == Piece.NotDefiend:
                        is_draw = False
            return is_draw

    所有代码如下;python版本

    '''
    blog:https://www.cnblogs.com/rianley
    author: rianley
    '''
    from tkinter import *
    from tkinter.messagebox import *
    from enum import Enum
    import sys
    class Piece(Enum):
        White = 1
        Black = 2
        NotDefiend = 3
    class Gobang:
        def __init__(self):
            """
            初始化
            """
            self.__root = Tk()
            self.__root.title("程小航版本五子棋")
            self.__width = 15
            self.__height = 15
            self.__radius = 30
            self.__w = (self.__width) * self.__radius * 2
            self.__h = (self.__height) * self.__radius * 2
            self.__root.geometry("{}x{}".format(self.__w, self.__h))
            self.__canvas = Canvas(self.__root, width=self.__w, height=self.__h)
            self.__last_x = -1
            self.__last_y = -1
            self.__last_point = None
            self.__color = Piece.White
            self.__pieces = [[Piece.NotDefiend for y in range(0, self.__height)] for x in range(0, self.__width)]
        def __draw_lines(self):
            for x in range(0, self.__width):
                self.__canvas.create_line(self.__radius + x * self.__radius * 2,
                                          self.__radius,
                                          self.__radius + x * self.__radius * 2,
                                          self.__radius + (self.__height - 1) * self.__radius * 2)
            for y in range(0, self.__height):
                self.__canvas.create_line(self.__radius,
                                          self.__radius + y * self.__radius * 2,
                                          self.__radius + (self.__width - 1) * self.__radius * 2,
                                          self.__radius + y * self.__radius * 2)
        def __get_current_position(self, x, y):
            """
            根据当前鼠标位置计算棋子位置
            """
            selected_x = max(0, min(int(x / (self.__radius * 2)), self.__width - 1))
            selected_y = max(0, min(int(y / (self.__radius * 2)), self.__height - 1))
            return (selected_x, selected_y)
        def __color_continius(self, arr, color):
            """
            判断某一颜色的棋子最大连续个数
            """
            max_count = 1
            _count = 1
            for i in range(0, len(arr) - 1):
                x1, y1 = arr[i]
                x2, y2 = arr[i + 1]
                if self.__pieces[x1][y1] == color and self.__pieces[x2][y2] == color:
                    _count += 1
                else:
                    _count = 1
                if _count >= max_count:
                    max_count = _count
            return max_count
        def __check_win(self, selected_x, selected_y, color):
            """
            判断某一颜色棋子的输赢,以当前棋子为中心,4子为半径判断四个方向即可
            """
            _row = []
            for x in range(selected_x - 4, selected_x + 5):
                if x >= 0 and x < self.__width:
                    _row.append((x, selected_y))
            if self.__color_continius(_row, color) >= 5:
                return True
            _col = []
            for x in range(selected_y - 4, selected_y + 5):
                if x >= 0 and x < self.__height:
                    _col.append((selected_x, x))
            if self.__color_continius(_col, color) >= 5:
                return True
            lb_rt = []
            for x in range(-4, 5):
                s_x = selected_x + x
                s_y = selected_y - x
                if s_x >= 0 and s_x < self.__width and s_y > 0 and s_y < self.__height:
                    lb_rt.append((s_x, s_y))
            if self.__color_continius(lb_rt, color) >= 5:
                return True
            lt_rb = []
            for x in range(-4, 5):
                s_x = selected_x + x
                s_y = selected_y + x
                if s_x >= 0 and s_x < self.__width and s_y > 0 and s_y < self.__height:
                    lt_rb.append((s_x, s_y))
            if self.__color_continius(lt_rb, color) >= 5:
                return True
            return False
    
        def __is_draw(self):
            """
            判断是否是和棋
            """
            is_draw = True
            for x in self.__pieces:
                for y in x:
                    if y == Piece.NotDefiend:
                        is_draw = False
            return is_draw
        def __bind_mouse_functions(self):
            """
            绑定鼠标事件
            """
            def move_handler(event):
                """
                鼠标移过棋盘,显示棋子
                """
                selected_x, selected_y = self.__get_current_position(event.x, event.y)
                # 如果已经有棋子了,当鼠标移动到点上时显示红色
                color = ("black" if self.__color == Piece.Black else "white") if self.__pieces[selected_x][
                                                                                     selected_y] == Piece.NotDefiend else "red"
                if selected_x != self.__last_x or selected_y != self.__last_y:
                    self.__canvas.delete(self.__last_point)
                    self.__last_point = self.__canvas.create_oval(
                        self.__radius + selected_x * self.__radius * 2 - self.__radius,
                        self.__radius + selected_y * self.__radius * 2 - self.__radius,
                        self.__radius + selected_x * self.__radius * 2 + self.__radius,
                        self.__radius + selected_y * self.__radius * 2 + self.__radius,
                        fill=color)
                    self.__last_x = selected_x
                    self.__last_y = selected_y
            def click_handler(event):
                """
                鼠标点击棋盘,落子并判断输赢
                """
                selected_x, selected_y = self.__get_current_position(event.x, event.y)
                if self.__pieces[selected_x][selected_y] != Piece.NotDefiend:
                    # 棋子已经存在,不可落子
                    pass
                else:
                    self.__pieces[selected_x][selected_y] = self.__color
                    color = "black" if self.__color == Piece.Black else "white"
                    self.__canvas.create_oval(self.__radius + selected_x * self.__radius * 2 - self.__radius,
                                              self.__radius + selected_y * self.__radius * 2 - self.__radius,
                                              self.__radius + selected_x * self.__radius * 2 + self.__radius,
                                              self.__radius + selected_y * self.__radius * 2 + self.__radius,
                                              fill=color)
                    # 如果某一方赢了,则重置游戏
                    if self.__check_win(selected_x, selected_y, self.__color):
                        message = "{} win!".format(color)
                        showinfo("Info", message)
                        self.__reset()
                    # 否则判断是否是和棋,如果是和棋,则重置
                    elif self.__is_draw():
                        message = "draw chess!"
                        showinfo("Info", message)
                        self.__reset()
                    if self.__color == Piece.White:
                        self.__color = Piece.Black
                    else:
                        self.__color = Piece.White
            #绑定事件canvas事件
            self.__canvas.bind('<Motion>', move_handler)
            self.__canvas.bind('<Button-1>', click_handler)
        def __reset(self):
            """
            重置游戏
            """
            self.__canvas.quit()
            self.__root.quit()
            self.__root.destroy()
            self.__init__()
            self.start()
        def start(self):
            # 绘制棋盘
            self.__canvas.pack()
            #绘制线
            self.__draw_lines()
            #鼠标经过是处理落棋,判断胜负条件
            self.__bind_mouse_functions()
            #循环执行
            self.__root.mainloop()
    if __name__ == "__main__":
        gobang = Gobang()
        gobang.start()

    朋友写的 js版本

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>五子棋</title>
        <style type="text/css">
            canvas{
                display: block;
                margin: 50px auto;
                box-shadow: -2px -2px 2px #F3F2F2, 5px 5px 5px #6F6767;
            }
        </style>
    </head>
    <body>
    <canvas id="mycanvas" width="600px" height="600px"></canvas>
    <script type="text/javascript">
        var chess = document.getElementById("mycanvas");
        var context = chess.getContext('2d');
        var me = true;
        var chessBox = [];//用于存放棋盘中落子的情况
        for(var i=0;i<20;i++){
            chessBox[i]=[];
            for(var j=0;j<20;j++){
                chessBox[i][j]=0;//初始值为0
            }
        }
        function drawChessBoard(){
            for(var i=0;i<20;i++){
                context.strokeStyle="#D6D1D1";
                context.moveTo(15+i*30,15);//垂直方向画15根线,相距30px;
                context.lineTo(15+i*30,585);
                context.stroke();
                context.moveTo(15,15+i*30);//水平方向画15根线,相距30px;棋盘为14*14;
                context.lineTo(585,15+i*30);
                context.stroke();
            }
        }
        drawChessBoard();//绘制棋盘
        function oneStep(i,j,k){
            context.beginPath();
            context.arc(15+i*30,15+j*30,13,0,2*Math.PI);//绘制棋子
            var g=context.createRadialGradient(15+i*30,15+j*30,13,15+i*30,15+j*30,0);//设置渐变
            if(k){    //k=true是黑棋,否则是白棋
                g.addColorStop(0,'#0A0A0A');//黑棋
                g.addColorStop(1,'#636766');
            }else {
                g.addColorStop(0,'#D1D1D1');//白棋
                g.addColorStop(1,'#F9F9F9');
            }
            context.fillStyle=g;
            context.fill();
            context.closePath();
        }
        var n=19;
        function f_x(arr) {
            for(var i in arr){
                let len = 1;
                let res = arr[i].split('_');
                let x = res[0];
                let y = res[1];
                let left = x;
                let right = x;
                while (left >= 0){
                    left -= 1
                    if(arr.includes(left+'_'+y)){
                        len+=1;
                    }else{
                        break;
                    }
                }
    
                while (right <= n){
                    right += 1
                    if(arr.includes(right+'_'+y)){
                        len+=1;
                    }else{
                        break;
                    }
                }
                if(len >= 5){
                    return arr[i];
                }
            }
            return  false;
        }
    
        function f_y(arr) {
            for(var i in arr){
                let len = 1;
                let res = arr[i].split('_');
                let x = res[0];
                let y = res[1];
                let left = y;
                let right = y;
                while (left >= 0){
                    left -= 1
                    if(arr.includes(x+'_'+left)){
                        len+=1;
                    }else{
                        break;
                    }
                }
    
                while (right <= n){
                    right += 1
                    if(arr.includes(x+'_'+right)){
                        len+=1;
                    }else{
                        break;
                    }
                }
                if(len >= 5){
                    return arr[i];
                }
            }
            return  false;
        }
    
        function f_xy1(arr) {
            for(var i in arr){
                let len = 1;
                let res = arr[i].split('_');
                let x = res[0];
                let y = res[1];
                let left = x;
                let right = y;
                while (left >= 0 && right >= 0){
                    left -= 1
                    right -= 1
                    if(arr.includes(left+'_'+right)){
                        len+=1;
                    }else{
                        break;
                    }
                }
                left = x;
                right = y;
                while (right <= n && left <= n){
                    left += 1
                    right += 1
                    if(arr.includes(left+'_'+right)){
                        len+=1;
                    }else{
                        break;
                    }
                }
                if(len >= 5){
                    return arr[i];
                }
            }
            return  false;
        }
    
        function f_xy2(arr) {
            for(var i in arr){
                let len = 1;
                let res = arr[i].split('_');
                let x = res[0];
                let y = res[1];
                let left = x;
                let right = y;
                while (left >= 0 && right <= n){
                    left -= 1
                    right += 1
                    if(arr.includes(left+'_'+right)){
                        len+=1;
                    }else{
                        break;
                    }
                }
                left = x;
                right = y;
                while (right >= 0 && left <= n){
                    left += 1
                    right -= 1
                    if(arr.includes(left+'_'+right)){
                        len+=1;
                    }else{
                        break;
                    }
                }
                if(len >= 5){
                    return arr[i];
                }
            }
            return  false;
        }
    
        var arr_all = [];
        var arr1 = [];
        var arr2 = [];
        var setIntervalxxx = setInterval(function () {
            while (1){
                var a = Math.floor(Math.random() * 20);
                var b = Math.floor(Math.random() * 20);
                var strs = a+'_'+b;
                if(arr_all.includes(strs)){
                    continue;
                }else{
                    break;
                }
            }
    
            arr_all.push(strs);
            if(arr1.length == arr2.length){
                arr1.push(strs);
                oneStep(a,b,true);
                var r1 = f_x(arr1);
                var r2 = f_y(arr1);
                var r3 = f_xy1(arr1);
                var r4 = f_xy2(arr1);
                if(r1 || r2 || r3 || r4){
                    alert('黑棋赢!!!');
                    console.log(r1,r2,r3,r4,'黑棋赢!!!',arr1);
                    clearInterval(setIntervalxxx);
                }
            }else{
                arr2.push(strs);
                oneStep(a,b,false);
                var r1 = f_x(arr2);
                var r2 = f_y(arr2);
                var r3 = f_xy1(arr2);
                var r4 = f_xy2(arr2);
                if(r1 || r2 || r3 || r4){
                    alert('白棋赢!!!');
                    console.log(r1,r2,r3,r4,'白棋赢!!!',arr2);
                    clearInterval(setIntervalxxx);
                }
            }
        },200);
    
    
        chess.onclick=function(e){
            var x = e.offsetX;//相对于棋盘左上角的x坐标
            var y = e.offsetY;//相对于棋盘左上角的y坐标
            var i = Math.floor(x/30);
            var j = Math.floor(y/30);
            if( chessBox[i][j] == 0 ) {
                oneStep(i,j,me);
                if(me){
                    chessBox[i][j]=1;
    
                }else{
                    chessBox[i][j]=2;
    
                }
                me=!me;//下一步白棋
            }
        }
    </script>
    </body>
    </html>
  • 相关阅读:
    公钥基础设施PKI 简介
    密码库LibTomcrypt的内容介绍及分析
    trace
    winform(C#)拖拽实现获得文件路径
    无线网络技术
    设备控制选项的部分列表
    dll #pragma data_seg注意事项
    RFC
    奥运火炬传递路线
    WMIC命令大全
  • 原文地址:https://www.cnblogs.com/rianley/p/14955383.html
Copyright © 2011-2022 走看看