连连看

第一种思路代码

连连看初始化,判断可通

package com.yelinlan.game.service;
import com.yelinlan.game.utils.Common;
import com.yelinlan.game.utils.PosType;
import java.util.Random;
/**
 * @项目名称: game
 * @类名称: ConnMap
 * @类描述: 连连看初始化,判断可通
 * @创建人: 夜林蓝
 * @创建时间: 2020/3/21 19:54
 **/
public class ConnMap {
    public char[][] conn = new char[10][10];
    protected int row = 10;
    protected int col = 10;
    //坐标(x,y)自己定义
    public PosType start;
    public PosType end;
    public ConnMap() {
    }
    public ConnMap(int row, int col) {
		//偶数个
        if ((row * col) % 2 == 0) {
            this.conn = new char[row][col];
            this.row = row;
            this.col = col;
        }
    }

    /**
     * @return : void
     * @方法名 : initMaze
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/7 18:23
     * @功能描述 : 初始化连连看
     */
    public void initMaze() {
        String baseChar = "ABCDEFGHJKL";
        int charLen = baseChar.length();
        Random rand = new Random();
        char val = baseChar.charAt(rand.nextInt(charLen));
        //初始化
        for (int i = 0; i < conn.length; i++) {
            for (int j = 0; j < conn.length; j++) {
                conn[i][j] = EMPTY;
            }
        }
        //随机阵
        char[] tempC = new char[(row - 2) * (col - 2)];
        for (int i = 0; i < (row - 2) * (col - 2) / 2; i++) {
            tempC[2 * i] = baseChar.charAt(rand.nextInt(charLen));
            tempC[2 * i + 1] = tempC[2 * i];
        }
        randChar(tempC);
        for (int i = 1; i < conn.length - 1; i++) {
            for (int j = 1; j < conn.length - 1; j++) {
                conn[i][j] = tempC[(i - 1) * (conn.length - 2) + j - 1];
            }
        }
    }

    /**
     * @return : void
     * @方法名 : randChar
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/20 2:51
     * @功能描述 : 随机字符数组
     */
    public void randChar(char[] arr) {
        Random rand = new Random();
        int len = arr.length;
        for (int i = 0; i < len; i++) {
            int index = rand.nextInt(len - i) + i;
            char temp = arr[index];
            arr[index] = arr[i];
            arr[i] = temp;
        }
    }
	/**
	 * @return : void
	 * @方法名 : randChar
	 * @创建人 : 夜林蓝
	 * @创建日期 : 2020/3/20 2:51
	 * @功能描述 : 是否可消除
	 */
    public boolean canPass(PosType start, PosType end) {
        this.start = start;
        this.end = end;
        return lean(start, end);
    }

    /**
     * @return : boolean
     * @方法名 : horizonalMid
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:42
     * @功能描述 : 水平是否有障碍
     */
    public boolean horizonalMid(PosType start, PosType end) {
        for (int i = Common.min(start.y, end.y); i <= Common.max(start.y, end.y); i++) {
            if (conn[start.x][i] != EMPTY) {
                if (isStartOrEndPosition(start.x,i)) {
                    continue;
                }
                return false;
            }
        }
        return true;
    }

    /**
     * @return : boolean
     * @方法名 : verticalUp
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:46
     * @功能描述 : 垂直是否有障碍
     */
    public boolean verticalMid(PosType start, PosType end) {
        //中间水平
        for (int i = Common.min(start.x, end.x); i <= Common.max(start.x, end.x); i++) {
            if (conn[i][start.y] != EMPTY) {
                if (isStartOrEndPosition(i,start.y)) {
                    continue;
                }
                return false;
            }
        }
        return true;
    }

    /**
     * @return : boolean
     * @方法名 : lean
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:57
     * @功能描述 : 斜线上 先水平后垂直
     */
    public boolean leanHV(PosType start, PosType end) {
        //先水平后垂直
        for (int i = 0; i < row; i++) {
            PosType posStart = new PosType(start.x, i);
            PosType posEnd = new PosType(end.x, i);
            //垂直通 水平通
            if (verticalMid(posStart, posEnd) && horizonalMid(start, posStart) && horizonalMid(posEnd, end)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return : boolean
     * @方法名 : lean
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:57
     * @功能描述 : 斜线上 先垂直后水平
     */
    public boolean leanVH(PosType start, PosType end) {
        //先垂直后水平
        for (int i = 0; i < col; i++) {
            PosType posStart = new PosType(i, start.y);
            PosType posEnd = new PosType(i, end.y);
            //垂直通 水平通
            if (horizonalMid(posStart, posEnd) && verticalMid(start, posStart) && verticalMid(posEnd, end)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return : boolean
     * @方法名 : lean
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 21:50
     * @功能描述 : 斜着
     */
    public boolean lean(PosType start, PosType end) {
        boolean leanhv = leanHV(start, end);
        boolean leanvh = leanVH(start, end);
        return leanhv || leanvh;
    }

 /**
     * 判断是否是起点或终点 (解决bug)
     * @return
     */
   boolean isStartOrEndPosition(int x,int y){
       return  (x==this.start.x && y==this.start.y)||(x==this.end.x && y==this.end.y);
    }
    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }
}

控制层调用

package com.yelinlan.game.Actinon;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.yelinlan.game.service.ConnMapCopy;
import com.yelinlan.game.utils.FileUtils;
import com.yelinlan.game.utils.PosType;
import com.yelinlan.game.utils.StringUtils;
import org.jboss.logging.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @项目名称: game
 * @类名称: LinkGame
 * @类描述:
 * @创建人: 夜林蓝
 * @创建时间: 2020/3/20 22:22
 **/
@Controller
@RequestMapping(value = "/main")
public class LinkGameCopy {
    private Logger logger = Logger.getLogger(LinkGameCopy.class);

    @RequestMapping("/login")
    public String login() {
        return "LinkGame";
    }

    @RequestMapping(value = "/initLinkGame")
    @ResponseBody
    public Object initLinkGame(@RequestBody Map<String, Object> paramMap, HttpServletRequest req) throws IOException {
        //矩阵大小
        Integer size = Integer.parseInt(Objects.toString(paramMap.get("size"), ""));
        ConnMapCopy maze = new ConnMapCopy(size, size);
        maze.initMaze();
        //一开始使用的session存取,发现在跨域的时候,数据没了。所以就存文件了,可以放数据库
        FileUtils.fileLinesWrite("F:maze.json", JSON.toJSONString(maze), false);
        return Promot(maze, "加载成功", 1);
    }

    @RequestMapping(value = "/doLinkGame")
    @ResponseBody
    public Object doLinkGame(@RequestBody Map<String, Object> paramMap, HttpServletRequest req) {
        ConnMapCopy maze = null;
        try {
            List<String> stringList = FileUtils.readFileContent("F:maze.json");
            String mazeStr = "";
            for (String s : stringList) {
                mazeStr += s;
            }
            maze = JSON.parseObject(mazeStr, ConnMapCopy.class);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Promot(null, "未初始化", 0);
        }
        //获取位置,一定不为空
        String pos_x = Objects.toString(paramMap.get("pos_x"));
        String pos_y = Objects.toString(paramMap.get("pos_y"));
        String pos_a = Objects.toString(paramMap.get("pos_a"));
        String pos_b = Objects.toString(paramMap.get("pos_b"));

        Integer x_a = StringUtils.toInteger(pos_x);
        Integer y_a = StringUtils.toInteger(pos_y);
        Integer x_b = StringUtils.toInteger(pos_a);
        Integer y_b = StringUtils.toInteger(pos_b);
        PosType startPosType = new PosType(x_a, y_a);
        PosType endPosType = new PosType(x_b, y_b);
        if (StringUtils.isBlank(maze.conn[x_a][y_a]) || StringUtils.isBlank(maze.conn[x_b][y_b])) {
            return Promot(null, "未选中有效范围", 0);
        }
        if (!(maze.conn[x_a][y_a] == maze.conn[x_b][y_b])) {
            return Promot(null, "无法删除,两个完全不一样", 0);
        }
        if (startPosType.equals(endPosType)) {
            return Promot(null, "不能消除自己", 0);
        }
        if (!(startPosType.x < maze.getRow() && startPosType.x >= 0 && startPosType.y < maze.getCol() && startPosType.y >= 0)) {
            return Promot(null, "越界", 0);
        }
        if (!(endPosType.x < maze.getRow() && endPosType.x >= 0 && endPosType.y < maze.getCol() && endPosType.y >= 0)) {
            return Promot(null, "越界", 0);
        }
        if (maze.canPass(startPosType, endPosType)) {
            maze.conn[x_a][y_a] = ' ';
            maze.conn[x_b][y_b] = ' ';
            if (clearAll(maze)) {
                FileUtils.fileLinesWrite("F:maze.json", "", false);
                return Promot(maze, "胜利", 1);
            }
            FileUtils.fileLinesWrite("F:maze.json", JSON.toJSONString(maze), false);
            return Promot(maze, "加油", 1);
        }
        FileUtils.fileLinesWrite("F:maze.json", JSON.toJSONString(maze), false);
        return Promot(maze, "消除失败", 0);
    }
    /**
     * @return : boolean
     * @方法名 : clearAll
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/20 23:35
     * @功能描述 : 已消除完毕
     */
    public boolean clearAll(ConnMapCopy maze) {
        for (int i = 0; i < maze.conn.length; i++) {
            for (int j = 0; j < maze.conn.length; j++) {
                if (maze.conn[i][j] != maze.EMPTY) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 返回信息处理
     *
     * @param maze
     * @param infomation
     * @param state
     * @return
     */
    private Map<String, Object> Promot(ConnMapCopy maze, String infomation, int state) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("maze", maze);
        map.put("infomation", infomation);
        map.put("state", state);
        return map;
    }
}

前端页面(springboot template)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<script th:src="${'/js/jquery.min.js'}" type="text/javascript"></script>
<script th:src="${'/js/bootstrap.min.js'}" type="text/javascript"></script>
<link th:href="${'/css/bootstrap.min.css'}" rel="stylesheet"/>

<script type="text/javascript">
	<!--已点中几个-->
    count = 0;
    pos_x = -1;
    pos_y = -1;
    pos_a = -1;
    pos_b = -1;
    curObj_xy = null;
    curObj_ab = null;

    function pick(curObj, x, y) {
        if (count == 0) {
            pos_x = x;
            pos_y = y;
            curObj_xy = curObj;
            $(curObj).css("font-size", "35px");
        }
        if (count == 1) {
            pos_a = x;
            pos_b = y;
            curObj_ab = curObj;
            $(curObj).css("font-size", "35px");
        }
        count++;
        if (count == 2) {
            var paramMap = {
                "pos_x": pos_x,
                "pos_y": pos_y,
                "pos_a": pos_a,
                "pos_b": pos_b
            }
			<!--点中两个就发送请求-->
            $.ajax({
                url: '/main/doLinkGame',
                type: 'post',
                dataType: 'json',
                contentType: 'application/json',
                data: JSON.stringify(paramMap),
                success: function (data) {
                    if (data.state == 1) {
                        if (data.infomation == "胜利") {
                            $("#btn").css("display", "inline");
                        } else {
                            $("#btn").css("display", "none");
                        }
                        //success
                        var maze = data.maze;
                        var row = maze.row;
                        var col = maze.col;
                        var conn = maze.conn;
                        var str = "";
                        str += (row - 2) + 'X' + (col - 2);
                        $("#default").html(str);
                        $("#info").html(data.infomation);
                        $("#info").css("color", "green");
                        str = "<table  style='margin: auto'>";
                        for (var i = 1; i < row - 1; i++) {
                            str += "<tr>";
                            for (var j = 1; j < col - 1; j++) {
                                if (conn[i][j] == ' ') {
                                    str += "<td >";
                                    str += conn[i][j];
                                    str += "</td>";
                                } else {
                                    str += "<td οnclick='pick(this," + i + "," + j + ")'>";
                                    str += conn[i][j];
                                    str += "</td>";
                                }
                            }
                            str += "</tr>";
                        }
                        str += " </table>";
                        $("#maze").html(str);
                    } else if (data.state == 0) {
                        $("#info").html(data.infomation);
                        $("#info").css("color", "red");
                    } else {
                        alert("无状态码,真奇怪。")
                    }
                    count = 0;
                    $(curObj_xy).css("font-size", "25px");
                    $(curObj_ab).css("font-size", "25px");
                },
                error: function () {
                    alert('ERROR')
                }
            })
        }
    }
<!--初始化-->
    function go() {
        $.ajax({
            url: '/main/initLinkGame',
            type: 'post',
            dataType: 'json',
            contentType: 'application/json',
            data: JSON.stringify({'size': '10'}),
            success: function (data) {
                if (data.state == 1) {
                    //success
                    var maze = data.maze;
                    var row = maze.row;
                    var col = maze.col;
                    var conn = maze.conn;
                    var connTemp = maze.connTemp;
                    var str = "";
                    str += (row - 2) + 'X' + (col - 2);
                    $("#default").html(str);
                    $("#info").html(data.infomation);
                    $("#btn").css("display", "none");

                    str = "<table style='margin: auto'  >";
                    for (var i = 1; i < row - 1; i++) {
                        str += "<tr>";
                        for (var j = 1; j < col - 1; j++) {
                            str += "<td  οnclick='pick(this," + i + "," + j + ")'>";
                            str += conn[i][j];
                            str += "</td>";
                        }
                        str += "</tr>";
                    }
                    str += " </table>";
                    $("#maze").html(str);
                } else {
                    alert("无状态码,真奇怪。")
                }
            },
            error: function () {
                alert('ERROR')
            }
        })
    }


</script>
<head>
    <meta charset='UTF-8'>
    <title>LinkGame</title>
    <style>
        td{
            font-family: Arial;
            font-size: 20px;
            text-align: center;
            width: 60px;
            height: 60px;
            border: solid lightblue 2px;
        }
    </style>
</head>
<body style="background-color: bisque">
<div style="text-align: center;"><span style="font-size: 40px;color: #5bc0de">连连看</span></div>
<div style="text-align: center;"><span id="default" style="font-size: 15px;color: green;">默认</span></div>
<hr>
<div style="text-align: center;"><span id="info" style="font-size: 30px;color: green;">默认</span></div>
<div style="text-align: center;">
    <button onclick='go()' id="btn" style="display: inline">开始</button>
</div>
<div id="maze"></div>
</body>
</html>

核心代码(判断可消)

	/**
	 * @return : void
	 * @方法名 : randChar
	 * @创建人 : 夜林蓝
	 * @创建日期 : 2020/3/20 2:51
	 * @功能描述 : 是否可消除
	 */
    public boolean canPass(PosType start, PosType end) {
        this.start = start;
        this.end = end;
        return lean(start, end);
    }

    /**
     * @return : boolean
     * @方法名 : horizonalMid
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:42
     * @功能描述 : 水平是否有障碍
     */
    public boolean horizonalMid(PosType start, PosType end) {
        for (int i = Common.min(start.y, end.y); i <= Common.max(start.y, end.y); i++) {
            if (conn[start.x][i] != EMPTY) {
                if (isStartOrEndPosition(start.x,i)) {
                    continue;
                }
                return false;
            }
        }
        return true;
    }

    /**
     * @return : boolean
     * @方法名 : verticalUp
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:46
     * @功能描述 : 垂直是否有障碍
     */
    public boolean verticalMid(PosType start, PosType end) {
        //中间水平
        for (int i = Common.min(start.x, end.x); i <= Common.max(start.x, end.x); i++) {
            if (conn[i][start.y] != EMPTY) {
                if (isStartOrEndPosition(i,start.y)) {
                    continue;
                }
                return false;
            }
        }
        return true;
    }

    /**
     * @return : boolean
     * @方法名 : lean
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:57
     * @功能描述 : 斜线上 先水平后垂直
     */
    public boolean leanHV(PosType start, PosType end) {
        //先水平后垂直
        for (int i = 0; i < row; i++) {
            PosType posStart = new PosType(start.x, i);
            PosType posEnd = new PosType(end.x, i);
            //垂直通 水平通
            if (verticalMid(posStart, posEnd) && horizonalMid(start, posStart) && horizonalMid(posEnd, end)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return : boolean
     * @方法名 : lean
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 20:57
     * @功能描述 : 斜线上 先垂直后水平
     */
    public boolean leanVH(PosType start, PosType end) {
        //先垂直后水平
        for (int i = 0; i < col; i++) {
            PosType posStart = new PosType(i, start.y);
            PosType posEnd = new PosType(i, end.y);
            //垂直通 水平通
            if (horizonalMid(posStart, posEnd) && verticalMid(start, posStart) && verticalMid(posEnd, end)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return : boolean
     * @方法名 : lean
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/21 21:50
     * @功能描述 : 斜着
     */
    public boolean lean(PosType start, PosType end) {
        boolean leanhv = leanHV(start, end);
        boolean leanvh = leanVH(start, end);
        return leanhv || leanvh;
    }

 /**
     * 判断是否是起点或终点 (解决bug)
     * @return
     */
   boolean isStartOrEndPosition(int x,int y){
       return  (x==this.start.x && y==this.start.y)||(x==this.end.x && y==this.end.y);
    }

思路

从两个地方判断(先水平后垂直,先垂直之后水平)

在这里插入图片描述

反思

这个思路简单,我做成了页面,便于玩。自己的逻辑还是不行。
这个问题,是由于一个朋友面试遇到的,我想解决。
BUT,当我刚听到,我的直觉告诉我,
应该可以用迷宫算法解决(但这会让代码复杂化,逻辑也很简单)。
思路:(回溯法遍历,也就是走迷宫,找到所有的解)
只拿到拐点数在区间[0,2]上的解,如果找到则可消,直到遍历所有结果。
因为:

在这里插入图片描述

第二种思路代码

迷宫思路(回溯法)的核心代码

//递归遍历(效率低)
publiczhuyaooConn(char[][] co, PosType pos) {
		//到达终点
        if (pos.equals(end)) {
        //拿到拐角数
            num =Common.min(countConner(record), num);
        } else{
        //一旦拐角数在(2,+00),放弃这一次。进行下一次
            if(countConner(record)<=2) {
            //四个方向探索
                for (int i = 1; i <= 4; i++) {
                	//找到下一个可走点
                    PosType rePos = canVisit(co, pos, i);                
                    if (rePos != null) {
                    //记录两横坐标差(两个坐标之间关系)
                        int tempNum = ((rePos.x - pos.x) == 0) ? 0 : 1;
                        //装起来(可以用来统计拐点数)
                        record += tempNum;
                        //标记走过
                        mark(co, rePos, PASS, 0);
                        //继续找
                        doConn(co, rePos);
                        //走了,没走通,标记可走(这里如果标记PASSNOT
                        //,那么找不到所有可能解)
                        mark(co, rePos, EMPTY, 0);
                        //走了走不通,移除一个坐标差
                        record = record.substring(0, record.length() - 1);
                    }
                }
            }
        }
    }

主要

//调用
public void ConnGame(PosType start, PosType end) {
        copyConn();
        this.start = start;
        this.end = end;
        mark(connTemp, start, PASS, 0);
        mark(connTemp, end, EMPTY, 1);
        doConn(connTemp, start);
        System.out.println("拐角数 : " + num);
    }
//递归遍历(效率低)
publiczhuyaooConn(char[][] co, PosType pos) {
		//到达终点
        if (pos.equals(end)) {
        //拿到拐角数
            num =Common.min(countConner(record), num);
        } else{
        //一旦拐角数在(2,+00),放弃这一次。进行下一次
            if(countConner(record)<=2) {
            //四个方向探索
                for (int i = 1; i <= 4; i++) {
                	//找到下一个可走点
                    PosType rePos = canVisit(co, pos, i);                
                    if (rePos != null) {
                    //记录两横坐标差(两个坐标之间关系)
                        int tempNum = ((rePos.x - pos.x) == 0) ? 0 : 1;
                        //装起来(可以用来统计拐点数)
                        record += tempNum;
                        //标记走过
                        mark(co, rePos, PASS, 0);
                        //继续找
                        doConn(co, rePos);
                        //走了,没走通,标记可走(这里如果标记PASSNOT
                        //,那么找不到所有可能解)
                        mark(co, rePos, EMPTY, 0);
                        //走了走不通,移除一个坐标差
                        record = record.substring(0, record.length() - 1);
                    }
                }
            }
        }
    }
    /**
     * @return : boolean
     * @方法名 : canVisit
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/20 0:23
     * @功能描述 : 是否可走
     */
    protected PosType canVisit(char[][] conn, PosType pos, int direction) {
        PosType nextPosType = new PosType(pos.x, pos.y);
        switch (direction) {
            //DOWN = 1;
            case 1:
                nextPosType.x++;
                break;
            //RIGHT = 2;
            case 2:
                nextPosType.y++;
                break;
            //UP = 3;
            case 3:
                nextPosType.x--;
                break;
            // LEFT = 4;
            case 4:
                nextPosType.y--;
                break;
            default:
                return null;
        }
        //越界
        if (isOutOfXBounds(nextPosType)) {
            return null;
        }
        //障碍或已走过
        //BORDER PASSNOT PASS
        if (conn[nextPosType.x][nextPosType.y] != EMPTY) {
            return null;
        }
        pos = nextPosType;
        return pos;
    }

    
     /**
     * @return : boolean
     * @方法名 : isOutOfXBounds
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/7 13:20
     * @功能描述 : 坐标越界
     */
    public boolean isOutOfXBounds(PosType pos) {
        return !(pos.x < this.row && pos.x >= 0 && pos.y < this.col && pos.y >= 0);
    }
/**
     * @return : void
     * @方法名 : mark
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/7 11:50
     * @功能描述 : //todo 标记迷宫块
     */
    public void mark(char[][] co, PosType pos, char markSymbol, int state) {
        if (state != 0) {
            co[pos.x][pos.y] = markSymbol;
        } else {
            if (!pos.equals(end)) {
                co[pos.x][pos.y] = markSymbol;
            }
        }
    }

拐角数统计

/**
     * @return : int
     * @方法名 : countConner
     * @创建人 : 夜林蓝
     * @创建日期 : 2020/3/7 16:45
     * @功能描述 : 统计拐角次数
     */
    public int countConner(String str) {
        int count = 0;
        char[] chars = str.toCharArray();
        int len = chars.length;
        for (int i = 0; i < len - 1; i++) {
            if (chars[i] != chars[i + 1]) {
                count++;
            }
        }
        return count;
    }

在这里插入图片描述

结束语

虽然饶了弯路,也还是可以。毕竟繁琐的方法,又加深了回溯法理解因为再看数据结构树,可以写迷宫,所以决定来实现连连看。可是,总会绕弯路的,不可避免。还是动手之前,先动脑,不然忙活了半天,思路不清晰,纸笔不离手,算法多画画,思路好一点。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值