Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

cocos-lua学习笔记(九)动作

$
0
0

下面是所有动作相关的接口,摘自《cocos2d-Lua基础》

瞬时动作:

1.place:节点放置到某一位置

2.Flipx与Flipy:只能用于精灵,沿x或y轴反转

3.Show与Hide 显示和隐藏节点

4.CallFunc 动作结束的,启动的逻辑


有限时间动作

1.MoveTo 与 MoveBy

2.JumTo 与JumpBy

3.BezierTo 与BezierBy

4.ScaleTo与ScaleBy

5.RotateTo与RotateBy

6.FadeIn、FadeOut和FadeTo

7.TintTo 与TintBy

8.Blink

9.Animation

复合动作

1.DelayTime

2.Repeat与RepeatForever

3.Spawn

4.Sequence

5.Follow

变速动作

1.Speed

2.ActionBase ->这里有很多图

节点动作接口

node:runAction()

node:stopAction()

node:stopAllActions

node:stopAction(action)

node:stopActionByTag(tag)


node:setTag(tag)

action:setTag(tag)


node:getActionByTag(tag)

action:stopActionByTag(tag)


具体的接口怎么使用,直接上一个Demo展示


local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

function MainScene:ctor()
    self.backgroundLayer = display.newColorLayer(cc.c4f(128,128,128,255))
    self.backgroundLayer:addTo(self)

    -- preload frames to cache
    display.addSpriteFrames("grossini-aliases.plist", "grossini-aliases.png")
    
    -- run actions: 1 to 9
    self:run(1)
end

function MainScene:run(actionNum)
    self["action" .. actionNum](self)
end

--[[
Follow
]]
function MainScene:action1()
    -- 用在层跟随精灵中,固定摄像机到精灵身上
    local sprite1 = display.newSprite("1.png")
    sprite1:center()
    local move_left = cc.MoveBy:create(1.5, cc.p(display.width / 2, 0))
    local move_right = cc.MoveBy:create(3, cc.p(- display.width, 0))
    local seq = cc.Sequence:create(move_left, move_right, move_left)
    local rep = cc.RepeatForever:create(seq)
    sprite1:runAction(rep)
    sprite1:addTo(self.backgroundLayer)
    
    self.backgroundLayer:runAction(cc.Follow:create(sprite1))
end

--[[
MoveBy
]]
function MainScene:action2()
    local sprite2 = display.newSprite("2.png")
        :center()
        :addTo(self.backgroundLayer)
    -- true 翻转,false 重置为最初的状态
    local flipxAction = cc.FlipX:create(true)
    local moveTo = cc.MoveBy:create(1, cc.p(-300, 0))
    local action = cc.Sequence:create(moveTo, flipxAction, moveTo:reverse())
    sprite2:runAction(action)
end

--[[
Hide
]]
function MainScene:action3()
    local hideAction = cc.Hide:create()
    local moveTo = cc.MoveTo:create(1.5, cc.p(60, 60))
    local action = cc.Sequence:create(moveTo, hideAction)   

    local sprite1 = display.newSprite("1.png")
        :center()
        :addTo(self.backgroundLayer)
        :runAction(action)
end

--[[
CallFunc
]]
function MainScene:action4()
    -- 判断顺序动画执行结束
    local callback = cc.CallFunc:create(function() print("In callback function") end)
    local moveTo = cc.MoveTo:create(2, cc.p(0, 0))
    local action = cc.Sequence:create(moveTo, callback)

    local sprite1 = display.newSprite("1.png")
        :center()
        :addTo(self.backgroundLayer)
        :runAction(action)
end

--[[
贝塞尔曲线
]]
function MainScene:action5()
    local action = cc.BezierTo:create(2, {cc.p(display.right, display.top), cc.p(200, 200), cc.p(50, 100)}) 

    local sprite1 = display.newSprite("1.png")
        :pos(0, 0)
        :addTo(self.backgroundLayer)
        :runAction(action)
end

--[[
FadeTo
]]
function MainScene:action6()
    local action = cc.FadeTo:create(2, 0)

    local sprite1 = display.newSprite("1.png")
        :center()
        :addTo(self.backgroundLayer)
        :runAction(action)
end

--[[
帧动画
]]
function MainScene:action7()

    local frames = display.newFrames("grossini_dance_%02d.png", 1, 14)
    local animation = display.newAnimation(frames, 0.2)
    local animate = cc.Animate:create(animation)

    local sprite1 = display.newSprite("#grossini_dance_01.png")
        :center()
        :addTo(self.backgroundLayer)
        :runAction(animate)
end

--[[
延迟动作
]]
function MainScene:action8()
    local move = cc.MoveBy:create(1, cc.vertex2F(150,0))
    local action = cc.Sequence:create(move, cc.DelayTime:create(2), move:reverse())

    local sprite1 = display.newSprite("1.png")
        :center()
        :addTo(self.backgroundLayer)
        :runAction(action)
end

--[[
变速动作
]]
function MainScene:action9()
    local action = cc.EaseSineOut:create(cc.MoveBy:create(2, cc.p(300, 0)))
    local sprite1 = display.newSprite("1.png")
        :center()
        :addTo(self.backgroundLayer)
        :runAction(action)
end

function MainScene:onEnter()
end

function MainScene:onExit()
end

return MainScene


作者:hiwoshixiaoyu 发表于2017/11/21 9:22:55 原文链接
阅读:32 评论:0 查看评论

cocos-lua学习笔记(十)事件---全局调度器

$
0
0

全局帧调度器

每一帧描画都会触发,windows上窗口移动和最小化的时候会暂停描画。

scheduler.scheduleUpdateGlobal(onInterval) 每一帧调用

全局自定义调度器

指定调度器的时间

scheduler.scheduleGlobal(onInterval, 0.5)  0.5秒调用一次


全局延时调度器

等待指定时间后执行一次回调函数

scheduler.performWithDelayGlobal(onInterval, 0.5)  延时0.5秒调用


local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

local scheduler = require(cc.PACKAGE_NAME .. ".scheduler")

function MainScene:ctor()
	-- 全局帧调度器
	local function onInterval(dt)
		print("update")
	end
	scheduler.scheduleUpdateGlobal(onInterval)

	-- 全局自定义调度器
	local function onInterval(dt)
		print("Custom")
	end
	scheduler.scheduleGlobal(onInterval, 0.5)

	-- 全局延时调度器
	local function onInterval(dt)
		print("once")
	end
	scheduler.performWithDelayGlobal(onInterval, 0.5)
end

return MainScene

大家看一下控制台吧,感觉像是爆炸了。


作者:hiwoshixiaoyu 发表于2017/11/21 9:29:22 原文链接
阅读:15 评论:0 查看评论

以太坊下载地址及相关文档

$
0
0

以太坊下载地址

该网站提供了,Linux,Windows,Mac,源码等下载。
https://ethereum.github.io/go-ethereum/downloads/

go语言版本

源代码地址:https://github.com/ethereum/go-ethereum
管理操作API地址:
https://github.com/ethereum/go-ethereum/wiki/Management-APIs
JsonRPC地址:https://github.com/ethereum/wiki/wiki/JSON-RPC
启动命令参数列表地址:https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options

作者:wo541075754 发表于2017/11/21 9:45:40 原文链接
阅读:11 评论:0 查看评论

【蓝桥杯】【奇怪的分式】

$
0
0

题目
上小学的时候,小明经常自己发明新算法。一次,老师出的题目是:
1/4 乘以 8/5
小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png)
老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!
对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢?
请写出所有不同算式的个数(包括题中举例的)。
显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。
但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!
注意:答案是个整数(考虑对称性,肯定是偶数)。请通过浏览器提交。不要书写多余的内容。

分析
思想与“马虎的算式”相同,在9个数字的数组中选4个数字填入4个元素的数组,要搜索出所有可能的情况,利用递归函数 DFS ,深度优先搜索。然后结合“有理数类”(Rational)来验证满足条件的答案。

源码

    private static HashSet<String> sets;

    public static void main(String[] args) {
        int[] a = new int[9];
        for (int i = 0; i < a.length; i++) {
            a[i] = i+1;
        }
        int[] b = new int[4];

        sets = new HashSet<String>();

        f(a, b, 0);

        for (String s : sets) {
            System.out.println(s);
        }

        System.out.println(sets.size());

    }

    private static void f(int[] a, int[] b, int index) {
        if(index == 4) {
            yz(b);
            return;
        }

        for (int i = 0; i < a.length; i++) {
            if(a[i] == -1) {
                continue;
            }else {
                b[index] = a[i];
                a[i] = -1;
            }
            //递归填充下一个数字
            f(a, b, index+1);

            {
                //回溯
                a[i] = b[index];
            }
        }

    }

    //b[0]/b[1] x  b[2]/b[3] == b[0]b[2]/b[1]b[3]
    private static void yz(int[] b) {
            Rational r1 = new Rational(b[0], b[1]);
            Rational r2 = new Rational(b[2], b[3]);
            Rational r = r1.mul(r2);
            Rational r3 = new Rational(b[0]*10+b[2], b[1]*10+b[3]);
//          System.out.println(r.toString() + "---------" + r3.toString());

            if(r.x == r3.x && r.y == r3.y) {
                //find
                String s = r1.toString() + " x " + r2.toString();
                sets.add(s);
            }
    }

结果
6/1 x 3/4
1/4 x 8/5
4/1 x 5/8
1/2 x 5/4
2/1 x 4/5
1/6 x 4/3
6

作者:bear_huangzhen 发表于2017/11/21 9:53:58 原文链接
阅读:0 评论:0 查看评论

ubuntu: 修改 默认编辑器

$
0
0

起因

因为觉得 gedit 太简陋, vimvinano 又没有UI那么直观,所以安装了Atom编辑器。但是每次还是默认从 gedir 打开文本,所以我需要 修改 默认编辑器 的设置。

步骤

Note:
这里就以 设置 Atom 为 默认编辑器 为例进行说明。

法一

sudo下分别进入以下两个文件:

/etc/gnome/defaults.list    
/usr/share/applications/mimeinfo.cache

均将文档中的 text/plain=gedit.desktop 修改为 text/plain=atom.desktop ,然后退出文档。

可以看到右键选项中 Atom 已经变为默认,则设置成功。

法二

进入 系统设置
这里写图片描述

Details 中进入 Default Applications ,修改 Calendar 项为 Atom
这里写图片描述

设置完成。

补充

装好 Atom 后,可以在终端直接用 sudo atom 新建或打开文本,也很方便:

sudo atom 1.txt

这里写图片描述



作者:JNingWei 发表于2017/11/21 9:55:04 原文链接
阅读:20 评论:0 查看评论

leetcode: 80. Remove Duplicates from Sorted Array II

$
0
0

Q

Follow up for “Remove Duplicates”:
What if duplicates are allowed at most twice?

For example,
Given sorted array nums = [1,1,1,2,2,3],

Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3. It doesn’t matter what you leave beyond the new length.

AC

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        i = 0
        for n in nums:
            if i < 2 or n > nums[i-2]:
                nums[i] = n
                i += 1
        return i


# Time:  O(n)
# Space: O(1)
class Solution2(object):
    def removeDuplicates(self, A):
        if not A:
            return 0

        last, i, same = 0, 1, False
        while i < len(A):
            if A[last] != A[i] or not same:
                same = A[last] == A[i]
                last += 1
                A[last] = A[i]
            i += 1
        return last + 1


if __name__ == "__main__":
    assert Solution().removeDuplicates([1, 1, 1, 2, 2, 3]) == 5


作者:JNingWei 发表于2017/11/21 10:08:02 原文链接
阅读:0 评论:0 查看评论

leetcode: 81. Search in Rotated Sorted Array II

$
0
0

Q

Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Write a function to determine if a given target is in the array.

The array may contain duplicates.

AC

class Solution(object):
    def search(self, nums, target):
        l, r = 0, len(nums)-1
        while l <= r:
            mid = l + (r-l)//2
            if nums[mid] == target:
                return True
            while l < mid and nums[l] == nums[mid]: # tricky part
                l += 1
            # the first half is ordered
            if nums[l] <= nums[mid]:
                # target is in the first half
                if nums[l] <= target < nums[mid]:
                    r = mid - 1
                else:
                    l = mid + 1
            # the second half is ordered
            else:
                # target is in the second half
                if nums[mid] < target <= nums[r]:
                    l = mid + 1
                else:
                    r = mid - 1
        return False


# Time:  O(logn)
# Space: O(1)
class Solution2(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left, right = 0, len(nums) - 1

        while left <= right:
            mid = left + (right - left) / 2

            if nums[mid] == target:
                return True
            elif nums[mid] == nums[left]:
                left += 1
            elif (nums[mid] > nums[left] and nums[left] <= target < nums[mid]) or \
                    (nums[mid] < nums[left] and not (nums[mid] < target <= nums[right])):
                right = mid - 1
            else:
                left = mid + 1
        return False


if __name__ == "__main__":
    assert Solution().search([3, 5, 1], 3) == True
    assert Solution().search([2, 2, 3, 3, 4, 1], 1) == True
    assert Solution().search([4, 4, 5, 6, 7, 0, 1, 2], 5) == True


作者:JNingWei 发表于2017/11/21 10:08:46 原文链接
阅读:0 评论:0 查看评论

leetcode: 82. Remove Duplicates from Sorted List II

$
0
0

Q

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.

AC

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """

        newhead = newtail = None
        seen = dict()
        p = head
        pp = None
        while p:
            dup = False
            while p.next and p.next.val==p.val:
                dup = True
                p = p.next
            if not dup:
                if not newhead:
                    newhead=newtail= p
                else:
                    newtail.next = p
                    newtail = p
            p = p.next
        if newtail:
            newtail.next = None
        return newhead


# Time:  O(n)
# Space: O(1)

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

    def __repr__(self):
        if self is None:
            return "Nil"
        else:
            return "{} -> {}".format(self.val, repr(self.next))

class Solution2(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        dummy = ListNode(0)
        pre, cur = dummy, head
        while cur:
            if cur.next and cur.next.val == cur.val:
                val = cur.val;
                while cur and cur.val == val:
                    cur = cur.next
                pre.next = cur
            else:
                pre.next = cur
                pre = cur
                cur = cur.next
        return dummy.next


if __name__ == "__main__":
    head, head.next, head.next.next, head.next.next.next, head.next.next.next.next, head.next.next.next.next.next, head.next.next.next.next.next.next\
        = ListNode(1), ListNode(2), ListNode(3), ListNode(3), ListNode(4), ListNode(4), ListNode(5)
    print Solution().deleteDuplicates(head)


作者:JNingWei 发表于2017/11/21 10:09:41 原文链接
阅读:0 评论:0 查看评论

leetcode: 83. Remove Duplicates from Sorted List

$
0
0

Q

Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.

AC

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        t_point = head
        while t_point:
            while t_point.next and t_point.next.val == t_point.val:
                t_point.next = t_point.next.next
            t_point = t_point.next
        return head


# Time:  O(n)
# Space: O(1)
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution2(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur = head
        while cur:
            runner = cur.next
            while runner and runner.val == cur.val:
                runner = runner.next
            cur.next = runner
            cur = runner
        return head

    def deleteDuplicates2(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head: return head
        if head.next:
            if head.val == head.next.val:
                head = self.deleteDuplicates(head.next)
            else:
                head.next = self.deleteDuplicates(head.next)
        return head


if __name__ == "__main__":
    head, head.next, head.next.next, head.next.next.next, head.next.next.next.next \
        = ListNode(1), ListNode(1), ListNode(2), ListNode(3), ListNode(3)
    assert Solution().deleteDuplicates(head).val == 1


作者:JNingWei 发表于2017/11/21 10:10:16 原文链接
阅读:0 评论:0 查看评论

leetcode: 84. Largest Rectangle in Histogram

$
0
0

Q

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

The largest rectangle is shown in the shaded area, which has area = 10 unit.

For example,
Given heights = [2,1,5,6,2,3],
return 10.

AC

class Solution(object):
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        heights.insert(0,0)
        heights.append(0)
        stack = []
        maxarea = 0
        for i, height in enumerate(heights):
            if not stack or heights[stack[-1]]<=height:
                stack.append(i)
            else:
                while stack and heights[stack[-1]]>height:
                    maxarea = max(maxarea, heights[stack[-1]]*(i-stack[-2]-1))
                    stack.pop()
                stack.append(i)
        right = stack[-1]
        stack.pop()
        while len(stack)>1:
            offset = right-stack[-1]
            maxarea = max(maxarea, heights[stack[-1]]*offset)
            stack.pop()
        return maxarea


# Time:  O(n)
# Space: O(n)
class Solution2(object):
    def largestRectangleArea(self, height):
        increasing, area, i = [], 0, 0
        while i <= len(height):
            if not increasing or (i < len(height) and height[i] > height[increasing[-1]]):
                increasing.append(i)
                i += 1
            else:
                last = increasing.pop()
                if not increasing:
                    area = max(area, height[last] * i)
                else:
                    area = max(area, height[last] * (i - increasing[-1] - 1 ))
        return area


if __name__ == "__main__":
    assert Solution().largestRectangleArea([2, 0, 2]) == 2
    assert Solution().largestRectangleArea([2, 1, 5, 6, 2, 3]) == 10


作者:JNingWei 发表于2017/11/21 10:10:48 原文链接
阅读:0 评论:0 查看评论

leetcode: 85. Maximal Rectangle

$
0
0

Q

Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing only 1’s and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

Return 6.

AC

class Solution(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        maxa = 0
        if not matrix:
            return 0
        vector = [0]* len(matrix[0])
        for r in matrix:
            for i, c in enumerate(r):
                if c == '0':
                    vector[i]=0
                else:
                    vector[i]+=1
            # print vector
            maxa = max(maxa, self.largestRectangleArea(vector[:]))
        return maxa

    def largestRectangleArea(self, heights):
        heights.insert(0,0)
        heights.append(0)
        stack = []
        maxarea = 0
        for i, height in enumerate(heights):
            if not stack or heights[stack[-1]]<=height:
                stack.append(i)
            else:
                while stack and heights[stack[-1]]>height:
                    maxarea = max(maxarea, heights[stack[-1]]*(i-stack[-2]-1))
                    stack.pop()
                stack.append(i)
        return maxarea


# Time:  O(n^2)
# Space: O(n)
# Ascending stack solution.
class Solution2(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        def largestRectangleArea(heights):
            increasing, area, i = [], 0, 0
            while i <= len(heights):
                if not increasing or (i < len(heights) and heights[i] > heights[increasing[-1]]):
                    increasing.append(i)
                    i += 1
                else:
                    last = increasing.pop()
                    if not increasing:
                        area = max(area, heights[last] * i)
                    else:
                        area = max(area, heights[last] * (i - increasing[-1] - 1 ))
            return area
        if not matrix:
            return 0
        result = 0
        heights = [0] * len(matrix[0])
        for i in xrange(len(matrix)):
            for j in xrange(len(matrix[0])):
                heights[j] = heights[j] + 1 if matrix[i][j] == '1' else 0
            result = max(result, largestRectangleArea(heights))
        return result


# Time:  O(n^2)
# Space: O(n)
# DP solution.
class Solution3(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if not matrix:
            return 0
        result = 0
        m = len(matrix)
        n = len(matrix[0])
        L = [0 for _ in xrange(n)]
        H = [0 for _ in xrange(n)]
        R = [n for _ in xrange(n)]
        for i in xrange(m):
            left = 0
            for j in xrange(n):
                if matrix[i][j] == '1':
                    L[j] = max(L[j], left)
                    H[j] += 1
                else:
                    L[j] = 0
                    H[j] = 0
                    R[j] = n
                    left = j + 1
            right = n
            for j in reversed(xrange(n)):
                if matrix[i][j] == '1':
                    R[j] = min(R[j], right)
                    result = max(result, H[j] * (R[j] - L[j]))
                else:
                    right = j
        return result


if __name__ == "__main__":
    matrix = ["01101", "11010", "01110", "11110", "11111", "00000"]
    assert Solution().maximalRectangle(matrix) == 9


作者:JNingWei 发表于2017/11/21 10:11:19 原文链接
阅读:0 评论:0 查看评论

leetcode: 86. Partition List

$
0
0

Q

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.

AC

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        h1 = t1 = ListNode(-1)
        h2 = t2 = ListNode(-1)
        dummy = head
        while dummy:
            if dummy.val < x:
                t1.next = dummy
                t1 = t1.next
            else:
                t2.next = dummy
                t2 = t2.next
            dummy = dummy.next
        t2.next = None
        t1.next = h2.next
        return h1.next


# Time:  O(n)
# Space: O(1)
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

    def __repr__(self):
        if self:
            return "{} -> {}".format(self.val, repr(self.next))

class Solution2(object):
    def partition(self, head, x):
        dummySmaller, dummyGreater = ListNode(-1), ListNode(-1)
        smaller, greater = dummySmaller, dummyGreater
        while head:
            if head.val < x:
                smaller.next = head
                smaller = smaller.next
            else:
                greater.next = head
                greater = greater.next
            head = head.next
        smaller.next = dummyGreater.next
        greater.next = None
        return dummySmaller.next


if __name__ == "__main__":
    head, head.next, head.next.next, head.next.next.next, head.next.next.next.next, head.next.next.next.next.next \
        = ListNode(1), ListNode(4), ListNode(3), ListNode(2), ListNode(5), ListNode(2)
    print Solution().partition(head, 3)


作者:JNingWei 发表于2017/11/21 10:11:51 原文链接
阅读:0 评论:0 查看评论

leetcode: 87. Scramble String

$
0
0

Q

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = “great”:

    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
       / \
      a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node “gr” and swap its two children, it produces a scrambled string “rgeat”.

    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
       / \
      a   t

We say that “rgeat” is a scrambled string of “great”.

Similarly, if we continue to swap the children of nodes “eat” and “at”, it produces a scrambled string “rgtae”.

    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a

We say that “rgtae” is a scrambled string of “great”.

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

AC

class Solution(object):
    def isScramble(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        if len(s1)!=len(s2) or set(s1)!=set(s2):
            return False
        if s1==s2:
            return True
        if not s1 and not s2:
            return True
        return self.recurse(s1, s2) or self.recurse(s1, s2[::-1])

    def recurse(self, s1, s2):
        from collections import defaultdict
        d = defaultdict(int)
        breakpoints = []
        for i, c in enumerate(s1[:-1]):
            d[c]+=1
            c2 = s2[i]
            d[c2]-=1
            same = True
            for cc in d:
                if d[cc]!=0:
                    same=False
                    break
            if same:
                breakpoints.append(i)
        for b in breakpoints:
            if self.isScramble(s1[:b+1], s2[:b+1]) and self.isScramble(s1[b+1:], s2[b+1:]):
                return True
        return False


# Time:  O(n^4)
# Space: O(n^3)
# DP solution
class Solution2(object):
    # @return a boolean
    def isScramble(self, s1, s2):
        if not s1 or not s2 or len(s1) != len(s2):
            return False
        if s1 == s2:
            return True
        result = [[[False for j in xrange(len(s2))] for i in xrange(len(s1))] for n in xrange(len(s1) + 1)]
        for i in xrange(len(s1)):
            for j in xrange(len(s2)):
                if s1[i] == s2[j]:
                    result[1][i][j] = True

        for n in xrange(2, len(s1) + 1):
            for i in xrange(len(s1) - n + 1):
                for j in xrange(len(s2) - n + 1):
                    for k in xrange(1, n):
                        if result[k][i][j] and result[n - k][i + k][j + k] or \
                                        result[k][i][j + n - k] and result[n - k][i + k][j]:
                            result[n][i][j] = True
                            break

        return result[n][0][0]


if __name__ == "__main__":
    assert Solution().isScramble("rgtae", "great") == True


作者:JNingWei 发表于2017/11/21 10:12:16 原文链接
阅读:0 评论:0 查看评论

leetcode: 88. Merge Sorted Array

$
0
0

Q

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.

AC

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: void Do not return anything, modify nums1 in-place instead.
        """
        while m and n:
            if nums1[m-1]>=nums2[n-1]:
                nums1[m+n-1] = nums1[m-1]
                m -= 1
            else:
                nums1[m+n-1]=nums2[n-1]
                n -= 1
        if n>0:
            for i in xrange(n):
                nums1[i] = nums2[i]


# Time:  O(n)
# Space: O(1)
class Solution2(object):
    def merge(self, A, m, B, n):
        last, i, j = m + n - 1, m - 1, n - 1
        while i >= 0 and j >= 0:
            if A[i] > B[j]:
                A[last] = A[i]
                last, i = last - 1, i - 1
            else:
                A[last] = B[j]
                last, j = last - 1, j - 1
        while j >= 0:
            A[last] = B[j]
            last, j = last - 1, j - 1


if __name__ == "__main__":
    A = [1, 3, 5, 0, 0, 0, 0]
    B = [2, 4, 6, 7]
    Solution().merge(A, 3, B, 4)
    assert A == [1, 2, 3, 4, 5, 6, 7]


作者:JNingWei 发表于2017/11/21 10:12:51 原文链接
阅读:0 评论:0 查看评论

《剑指offer》刷题笔记(分解让复杂问题简单):字符串的排列

$
0
0

《剑指offer》刷题笔记(分解让复杂问题简单):字符串的排列



前言

在计算机领域有一类算法叫分治法,即“分而治之”。采用的就是各个击破的思想,我们把分解后的小问题各个解决,然后把小问题的解决方案结合起来解决大问题。

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

解题思路

全排列,我们很快就想到递归。

首先,我们把一个字符串看成两部分组成:第一部分为它的第一个字符,第二部分为后面的所有字符。首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。第二步固定第一个字符,求后面的所有字符的排列。这个时候我们仍然把后面所有的字符分成两部分:后面字符的第一个字符,以及这个字符之后的所有字符,然后把第一个字符逐一和它后面的字符交换。

典型的递归思想,下面分别用C/C++和python实现,python还是那么的简单暴力。

C++版代码实现

class Solution {
public:
    vector<string> result;
    vector<string> Permutation(string str) {
        if(str.length() == 0)
            return result;
        Permutation1(str, 0);
        sort(result.begin(), result.end());
        return result;
    }

    void Permutation1(string str, int begin){
        if(begin == str.length()){
            result.push_back(str);
            return;
        }
        for(int i=begin; str[i] != '\0'; ++i){
            //如果有重复的,交换没什么卵用,所以直接跳过,其实这段话不加也行
            if(i != begin && str[begin] == str[i])
                continue;
            //交换
            swap(str[begin], str[i]);
            //递归
            Permutation1(str, begin+1);
            //复位
            swap(str[begin], str[i]);
        }
    }
};

Python版代码实现

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        # write code here
        if not ss:
            return []
        return sorted(list(set(map(''.join, itertools.permutations(ss)))))

系列教程持续发布中,欢迎订阅、关注、收藏、评论、点赞哦~~( ̄▽ ̄~)~

完的汪(∪。∪)。。。zzz

作者:u011475210 发表于2017/11/21 10:32:35 原文链接
阅读:53 评论:0 查看评论

数据结构与算法分析(Java语言描述)(30)—— 有权图的实现

$
0
0

使用 Edge.java 存放两节点之间的边

Edge.java

package com.dataStructure.weight_graph;

// 有权图的边
public class Edge<Weight extends Number & Comparable> implements Comparable<Edge> {
    private int v;  // 边的一个端点 v
    private int w;  // 边的另一个端点 w
    private Weight weight;  // 边的权重

    // 构造函数
    public Edge(int v, int w, Weight weight) {
        this.v = v;
        this.w = w;
        this.weight = weight;
    }

    // 构造函数
    public Edge(Edge<Weight> edge) {
        this.v = edge.v;
        this.w = edge.w;
        this.weight = edge.weight;
    }

    public String toString() {  // 输出边的信息
        return "" + this.v + "-" + this.w + ":" + this.weight;

    }

    public int getV() { // 返回节点 v
        return v;
    }

    public int getW() { // 返回节点 w
        return w;
    }

    public Weight getWeight() { // 返回边的权重
        return weight;
    }

    public int getAnotherNode(int x) {  // 输入边的一个端点,输出边的另一个端点
        return x == v ? v : w;
    }

    public int compareTo(Edge anotherEdge){ // 比较两个边的权重大小
        if (this.weight.compareTo(anotherEdge.weight) > 0)
            return 1;
        else if (this.weight.compareTo(anotherEdge.weight) < 0)
            return -1;
        else
            return 0;
    }
}

//public class Edge<Weight extends Number & Comparable> implements Comparable<Edge> {
//
//    private int a, b;    // 边的两个端点
//    private Weight weight;  // 边的权值
//
//    public Edge(int a, int b, Weight weight)
//    {
//        this.a = a;
//        this.b = b;
//        this.weight = weight;
//    }
//
//    public Edge(Edge<Weight> e)
//    {
//        this.a = e.a;
//        this.b = e.b;
//        this.weight = e.weight;
//    }
//
//    public int v(){ return a;} // 返回第一个顶点
//    public int w(){ return b;} // 返回第二个顶点
//
//    public Weight wt(){ return weight;}    // 返回权值
//
//    // 给定一个顶点, 返回另一个顶点
//    public int other(int x){
//        assert x == a || x == b;
//        return x == a ? b : a;
//    }
//
//    // 输出边的信息
//    public String toString(){
//        return "" + a + "-" + b + ": " + weight;
//    }
//
//    // 边之间的比较
//    public int compareTo(Edge that)
//    {
//        if( weight.compareTo(that.wt()) < 0 )
//            return -1;
//        else if ( weight.compareTo(that.wt()) > 0 )
//            return +1;
//        else
//            return  0;
//    }
//
//}

WeightedGraph.java

package com.dataStructure.weight_graph;

public interface WeightedGraph {
    public int V();

    public int E();

    public void addEdge(Edge e);

    boolean hasEdge(int v, int w);

    void show();

    public Iterable<Edge> adjacentNode(int v);
}

DenseGraph.java

package com.dataStructure.weight_graph;

import java.util.ArrayList;
import java.util.List;

// 稠密图 - 邻接矩阵
public class DenseGraph implements WeightedGraph {
    private int vertexCount;    // 节点数量
    private int edgeCount;  // 边数
    private Edge[][] adjacencyMatrix;   // 存放 Edge 的邻接矩阵
    private boolean directed;   // 是否为有向图

    // 构造函数,初始化私有字段
    public DenseGraph(int vertexCount, boolean directed) {
        this.vertexCount = vertexCount;
        this.edgeCount = 0;
        this.directed = directed;
        adjacencyMatrix = new Edge[vertexCount][vertexCount];

        for (int i = 0; i < vertexCount; i++)
            for (int j = 0; j < vertexCount; j++)
                adjacencyMatrix[i][j] = null;   // 邻接矩阵初始为空

    }

    public int V() {    // 返回节点数量
        return vertexCount;
    }

    public int E() {    // 返回边数
        return edgeCount;
    }

    public void addEdge(Edge e) {   // 添加一条边
        if (hasEdge(e.getV(), e.getW()))
            return;
        adjacencyMatrix[e.getV()][e.getW()] = new Edge(e);

        if( e.getV() != e.getW() && !directed )
            adjacencyMatrix[e.getW()][e.getV()] = new Edge(e.getW(), e.getV(), e.getWeight());

        edgeCount++;
    }

    public boolean hasEdge(int v, int w) {  // 判断两节点之间是否有边
        return adjacencyMatrix[v][w] != null;
    }

    public void show() {    // 打印邻接矩阵
        for( int i = 0 ; i < vertexCount ; i ++ ){
            for( int j = 0 ; j < vertexCount ; j ++ )
                if( adjacencyMatrix[i][j] != null )
                    System.out.print(adjacencyMatrix[i][j].getWeight()+"\t");
                else
                    System.out.print("NULL\t");
            System.out.println();
        }
    }

    public Iterable<Edge> adjacentNode(int v) { // 获取邻接节点
        List<Edge> list = new ArrayList<>();
        for (int i = 0;i<adjacencyMatrix[v].length;i++){
            if (adjacencyMatrix[v][i] != null)
                list.add(adjacencyMatrix[v][i]);
        }
        return list;
    }
}


//public class DenseWeightedGraph<Weight extends Number & Comparable>
//        implements WeightedGraph{
//
//    private int n;  // 节点数
//    private int m;  // 边数
//    private boolean directed;   // 是否为有向图
//    private Edge<Weight>[][] g;         // 图的具体数据
//
//    // 构造函数
//    public DenseWeightedGraph( int n , boolean directed ){
//        assert n >= 0;
//        this.n = n;
//        this.m = 0;    // 初始化没有任何边
//        this.directed = directed;
//        // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为null, 表示没有任和边
//        // false为boolean型变量的默认值
//        g = new Edge[n][n];
//        for(int i = 0 ; i < n ; i ++)
//            for(int j = 0 ; j < n ; j ++)
//                g[i][j] = null;
//    }
//
//    public int V(){ return n;} // 返回节点个数
//    public int E(){ return m;} // 返回边的个数
//
//    // 向图中添加一个边
//    public void addEdge(Edge e){
//
////        assert e.v() >= 0 && e.v() < n ;
////        assert e.w() >= 0 && e.w() < n ;
//
////        if( hasEdge( e.v() , e.w() ) )
////            return;
////
////        g[e.v()][e.w()] = new Edge(e);
////        if( e.v() != e.w() && !directed )
////            g[e.w()][e.v()] = new Edge(e.w(), e.v(), e.wt());
//
////        m ++;
//    }
//
//    // 验证图中是否有从v到w的边
//    public boolean hasEdge( int v , int w ){
//        assert v >= 0 && v < n ;
//        assert w >= 0 && w < n ;
//        return g[v][w] != null;
//    }
//
//    // 显示图的信息
//    public void show(){
//
//        for( int i = 0 ; i < n ; i ++ ){
//            for( int j = 0 ; j < n ; j ++ )
//                if( g[i][j] != null )
//                    System.out.print(g[i][j].getWeight()+"\t");
//                else
//                    System.out.print("NULL\t");
//            System.out.println();
//        }
//    }
//
//    // 返回图中一个顶点的所有邻边
//    // 由于java使用引用机制,返回一个Vector不会带来额外开销,
//    public Iterable<Edge<Weight>> adjacentNode(int v) {
//        assert v >= 0 && v < n;
//        List<Edge<Weight>> adjV = new ArrayList<>();
//        for(int i = 0 ; i < n ; i ++ )
//            if( g[v][i] != null )
//                adjV.add( g[v][i] );
//        return adjV;
//    }
//}

SparseGraph.java

package com.dataStructure.weight_graph;

import java.util.ArrayList;
import java.util.List;

public class SparseGraph implements WeightedGraph {
    private int vertexCount;
    private int edgeCount;
    private boolean directed;
    private List<Edge>[] adjacencyTable;

    public SparseGraph(int vertexCount, boolean directed) {
        this.vertexCount = vertexCount;
        this.edgeCount = 0;
        this.directed = directed;
        adjacencyTable = (ArrayList<Edge>[]) new ArrayList[vertexCount];

        for (int i = 0; i < adjacencyTable.length; i++)
                adjacencyTable[i] = new ArrayList<>();

    }

    public int V() {
        return vertexCount;
    }

    public int E() {
        return edgeCount;
    }

    public void addEdge(Edge e) {   // 添加一条边
        if (hasEdge(e.getV(), e.getW()))
            return;
        adjacencyTable[e.getV()].add(new Edge(e));

        if (e.getV() != e.getW() && !directed)
            adjacencyTable[e.getW()].add(new Edge(e.getW(), e.getV(), e.getWeight()));
        edgeCount++;
    }

    public boolean hasEdge(int v, int w) {  // 判断节点 v 和 w 之间是否有边
        for (Edge edge:adjacencyTable[v])
            if (edge.getAnotherNode(v) == w)
                return true;
        return false;
    }

    public void show() {    // 打印邻接表
        for( int i = 0 ; i < vertexCount ; i ++ ){
            System.out.print("vertex " + i + ":\t");
            for( int j = 0 ; j < adjacencyTable[i].size() ; j ++ ){
                Edge e = adjacencyTable[i].get(j);
                System.out.print( "( to:" + e.getAnotherNode(i) + ",wt:" + e.getWeight() + ")\t");
            }
            System.out.println();
        }
    }

    public Iterable<Edge> adjacentNode(int v) { // 返回邻接节点
        return adjacencyTable[v];
    }

//    private int n;  // 节点数
//    private int m;  // 边数
//    private boolean directed;   // 是否为有向图
//    private Vector<Edge<Weight>>[] g;   // 图的具体数据
//
//    // 构造函数
//    public SparseWeightedGraph( int n , boolean directed ){
//        assert n >= 0;
//        this.n = n;
//        this.m = 0;    // 初始化没有任何边
//        this.directed = directed;
//        // g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边
//        g = (Vector<Edge<Weight>>[])new Vector[n];
//        for(int i = 0 ; i < n ; i ++)
//            g[i] = new Vector<Edge<Weight>>();
//    }
//
//    public int V(){ return n;} // 返回节点个数
//    public int E(){ return m;} // 返回边的个数
//
//    // 向图中添加一个边, 权值为weight
//    public void addEdge(Edge e){
//
//        assert e.v() >= 0 && e.v() < n ;
//        assert e.w() >= 0 && e.w() < n ;
//
//        // 注意, 由于在邻接表的情况, 查找是否有重边需要遍历整个链表
//        // 我们的程序允许重边的出现
//
//        g[e.v()].add(new Edge(e));
//        if( e.v() != e.w() && !directed )
//            g[e.w()].add(new Edge(e.w(), e.v(), e.wt()));
//
//        m ++;
//    }
//
//    // 验证图中是否有从v到w的边
//    public boolean hasEdge( int v , int w ){
//
//        assert v >= 0 && v < n ;
//        assert w >= 0 && w < n ;
//
//        for( int i = 0 ; i < g[v].size() ; i ++ )
//            if( g[v].elementAt(i).other(v) == w )
//                return true;
//        return false;
//    }
//
//    // 显示图的信息
//    public void show(){
//
//        for( int i = 0 ; i < n ; i ++ ){
//            System.out.print("vertex " + i + ":\t");
//            for( int j = 0 ; j < g[i].size() ; j ++ ){
//                Edge e = g[i].elementAt(j);
//                System.out.print( "( to:" + e.other(i) + ",wt:" + e.wt() + ")\t");
//            }
//            System.out.println();
//        }
//    }
//
//    // 返回图中一个顶点的所有邻边
//    // 由于java使用引用机制,返回一个Vector不会带来额外开销,
//    public Iterable<Edge<Weight>> adj(int v) {
//        assert v >= 0 && v < n;
//        return g[v];
//    }
}

ReadWeightedGraph.java

package com.dataStructure.weight_graph;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
import java.util.Locale;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;

// 通过文件读取有全图的信息
public class ReadWeightedGraph{

    private Scanner scanner;

    // 由于文件格式的限制,我们的文件读取类只能读取权值为Double类型的图
    public ReadWeightedGraph(WeightedGraph graph, String filename){

        readFile(filename);

        try {
            int V = scanner.nextInt();
            if (V < 0)
                throw new IllegalArgumentException("number of vertices in a Graph must be nonnegative");
            assert V == graph.V();

            int E = scanner.nextInt();
            if (E < 0)
                throw new IllegalArgumentException("number of edges in a Graph must be nonnegative");

            for (int i = 0; i < E; i++) {
                int v = scanner.nextInt();
                int w = scanner.nextInt();
                Double weight = scanner.nextDouble();
                assert v >= 0 && v < V;
                assert w >= 0 && w < V;
                graph.addEdge(new Edge<Double>(v, w, weight));
            }
        }
        catch (InputMismatchException e) {
            String token = scanner.next();
            throw new InputMismatchException("attempts to read an 'int' value from input stream, but the next token is \"" + token + "\"");
        }
        catch (NoSuchElementException e) {
            throw new NoSuchElementException("attemps to read an 'int' value from input stream, but there are no more tokens available");
        }
    }

    private void readFile(String filename){
        assert filename != null;
        try {
            String basePath = (new File(this.getClass().getResource("").getPath())).toString();
            File file = new File(basePath + filename);
            if (file.exists()) {
                FileInputStream fis = new FileInputStream(file);
                scanner = new Scanner(new BufferedInputStream(fis), "UTF-8");
                scanner.useLocale(Locale.ENGLISH);
            }
            else
                throw new IllegalArgumentException(filename + " doesn't exist.");
        }
        catch (IOException ioe) {
            throw new IllegalArgumentException("Could not open " + filename, ioe);
        }
    }

}

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

作者:HeatDeath 发表于2017/11/21 11:04:00 原文链接
阅读:25 评论:0 查看评论

“敲代码”学编程的正确方式

$
0
0

【来信】
  老师您好!我自学编程的,我想向您咨询一下,关于敲代码的方法!
  第一:我先理解书上、视频的源码,然后根据自己对源码的理解,然后把代码的思路写下来,然后自己这个思路把代码敲出来,当我自己不懂的时候,再返回去看源码!
  第二:理解书、视频的源码,完全照抄一篇。
  我很长一段时间是使用第一种方法,但是我觉得好累啊!学得很慢,当我遇到一些难以理解的代码而且200多行的代码的时候,我感觉我虽然理解了代码,但是要我完全敲出来,总是会出错,当我全部功能实现之后,要花很长时间!我不知道我自己的这种方法是不是有问题,身边我也没有人可以请教!所以我想向您咨询一下这个问题!

【回复】
  很感动你的执着。初学遇上困难很正常,这一关过了,就可以迎接下一关的挑战了,不断过关,让自己的知识和能力上到新的高度,有辛苦,但是其乐无穷。
  从你描述的学法上,我先做些点评。
  “理解书、视频的源码,完全照抄一篇(遍?)”这个时期,我觉得不要照抄。“敲代码”靠的不是手指头,靠的是大脑。你首先要做的是阅读程序,深度的阅读。并且在读的时候,不要一下钻到细节中,先看结构。要解决的问题大致是清楚的,于是,程序有几大块,每块的任务是什么(你会发现,最宏观的,无非就是“输入-处理-输出”三块),然后再分解每一块。对十来行代码的程序这样阅读,等阅读200行,甚至2000行的程序时,这种思维就形成了,再不会被其中某个语法上的小疑惑困住了。照抄一遍会让你直接进入细节,忽视了结构,不利于你形成自己解决问题的能力。
  基于上面所说的阅读,在理解后,自己写代码。这时候,思路不清时,想结构,语法不清时,看语法即可。若写出了和源码不一样的程序,完全正常,不要追求一模一样。只要知道自己思路清楚,表达正确就可以了,甚至,在思路上、表达上和源码不一样,是件更好的事。当自己写得过程中糊涂了,有必要再回去看源码时,我也希望你能清晰地知道,是去发现思路(结构)上的问题,还是语法上的问题。语法上的问题,也完全可以去看有关的知识点,而不是源码。
  进入一个新领域学习,总是初时要慢。要学知识本身,还要学方法。从长远看,接受自己的慢起步。在做简单题的阶段,以及现在已经学一段时间后,可以回头再看,尝试一题多解(用多种思路/结构)和一义多表(同样的思路,用多种语法结构描述,如一段分支结构的逻辑,用if-else语句、switch语句、?:运算分别表示)的方式做一做,你学得东西就“活”了。
  以上是对你提问题的直接回答。
  再多说点。
  程序设计初学者,我特指学第一门编程语言的同学,感觉到的起步难就是源于两个方面:语言本身和解题思路。解决一个问题,两方面的能力都需要,但刻意地将这两个方面学着分开一些。初学做小项目时是这样,实际上,到成为高手后,做大项目、大工程,必然也是这样的,并且做宏观设计的人和最终用编程语言实现的人甚至不是一个部门的。阅读程序是学习过程中很重要的手段,先掌握结构,必要时将重点的语法部分再看一看,没必要时就不看了,用自己觉得更自然的语句去表达。而在写程序时,先将结构想清楚,甚至写出来(画流程图,或者就在源码中,用注释的方式标出来,以便后续填空),再考虑用什么样的语句表达。
  在学习过程中,注意一下及时总结。其实初学时,从语法角度,无非就是一些语句、表达式;从结构角度,顺序、分支、循环三种控制结构,再加上模块化程序设计机制等;从数据结构角度,简单变量到数组再到结构体等。学一段时间,将这些成份,以及它们之间的关系,在脑子中从宏观上织一织网,渐次再想到细节,你就不会被各种表象困扰了。
  就说这些。祝你学习顺利,也相信你能渡过难关。
  

作者:sxhelijian 发表于2017/11/21 11:04:13 原文链接
阅读:30 评论:0 查看评论

Unity Shader 学习笔记(16) 渲染纹理(Render Texture)

$
0
0

Unity Shader 学习笔记(16) 渲染纹理(Render Texture)

参考书籍:《Unity Shader 入门精要》
Unity 制作小地图(Minimap)系统 两种方法
官网文档:Graphics Command Buffers


渲染纹理(Render Texture)

  GPU允许把三维场景渲染到一个中间缓冲中,即渲染目标纹理(Render Target Texture, RTT),而不是传统的帧缓冲或后备缓冲。延迟渲染使用多重渲染目标(Multiple Render Target, MRT),即同时渲染到多个渲染目标纹理。
  Unity中使用渲染纹理通常有两种方式:
1. 在Project目录创建渲染纹理,摄像机中设置渲染目标为该纹理。可以模拟镜子效果、投影(如制作游戏的小地图)。
2. 屏幕后处理时使用GrabPass命令或OnRenderImage函数来获取当前屏幕图像,实现各种屏幕特效。

镜子效果(Mirror)

Properties {
    _MainTex ("Main Tex", 2D) = "white" {}  // 传入自己创建的RenderTexture
}


v2f vert(a2v v) {
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);

    o.uv = v.texcoord;
    o.uv.x = 1 - o.uv.x;        // 反转x分量

    return o;
}

fixed4 frag(v2f i) : SV_Target {
    return tex2D(_MainTex, i.uv);       // 直接输出反转后的纹理
}

玻璃效果(Glass)

反射从1到0,折射从0到1。玻璃后面的图像被“扭曲”。

  通过GrabPass获取屏幕图像,通常用于渲染透明物体。及对物体后面的图像做更复杂的处理,模拟折射效果等。虽然代码不包含混合指令,但往往需要把物体的渲染队列设置成透明队列(”Queue” = “Transparent”)。

实现原理:结合法线纹理修改法线信息,然后使用上一篇的Cubemap来模拟玻璃的反射,再用GrabPass获取玻璃后面的屏幕图像,最后用切线空间下的法线对屏幕做偏移。

Properties {
    _MainTex ("Main Tex", 2D) = "white" {}
    _BumpMap ("Normal Map", 2D) = "bump" {}                     // 法线纹理
    _Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}       // 反射纹理
    _Distortion ("Distortion", Range(0, 100)) = 10              // 折射扭曲程度
    _RefractAmount ("Refract Amount", Range(0.0, 1.0)) = 1.0    // 控制折射程度(0:只反射,1:只折射)
}

SubShader中:

// Transparent:在所有不透明物体渲染后再渲染。Opaque:确保在着色器替换时,该物体在需要时正确渲染。
Tags { "Queue"="Transparent" "RenderType"="Opaque" }

// 抓取屏幕图像的Pass,存入到纹理变量_RefractionTex中。
GrabPass { "_RefractionTex" }

Pass {
    ...

    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _BumpMap;
    float4 _BumpMap_ST;
    samplerCUBE _Cubemap;
    float _Distortion;
    fixed _RefractAmount;
    sampler2D _RefractionTex;           // 对应GrabPass指定的纹理名
    float4 _RefractionTex_TexelSize;    // 纹理大小。如256x512的纹理,值为(1/256, 1/512...

    struct v2f {
        float4 pos : SV_POSITION;
        float4 scrPos : TEXCOORD0;      // 屏幕图像的采样坐标
        ...
    };

    v2f vert (a2v v) {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);

        o.scrPos = ComputeGrabScreenPos(o.pos);         // 计算抓取的屏幕图像采样坐标,在UnityCG.cginc中定义。

        ... // 法线纹理采样,切线空间转换到世界空间等
        return o;
    }

    fixed4 frag (v2f i) : SV_Target {       
        float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
        fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

        // 获取切线空间下的法线方向
        fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));   

        // 对屏幕图像采样坐标进行偏移,模拟折射
        float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
        i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
        fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;     // 透射除法 计算得到屏幕坐标

        // 法线再转到世界空间,原理见前面第8篇
        bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));

        // 法线再转到世界空间
        bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
        // 计算反射方向
        fixed3 reflDir = reflect(-worldViewDir, bump);
        // 主纹理的采样,和立方体纹理的采样
        fixed4 texColor = tex2D(_MainTex, i.uv.xy);
        fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb;

        fixed3 finalColor = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;

        return fixed4(finalColor, 1);
    }
}

GrabPass支持的形式

  • 直接使用GrabPass{ },在后面Pass中直接使用_GrabTexture来访问图像。如果多个物体都这样抓取屏幕,Unity都会单独抓取屏幕,消耗较大。但每个物体屏幕图像不同。
  • 使用GrabPass {“TextureName”},如上例子。但Unity只会在每一帧时,为第一个使用TextureName纹理的物体抓一次屏幕,同时意味着所有物体都用这一张屏幕图像。

渲染纹理 和 GrabPass的比较

- 渲染纹理 GrabPass
实现难度 复杂,要创建纹理,额外相机,设置相机渲染目标,最后传入Shader或者Raw Image。 简单,只需几行代码即可抓取屏幕。
效率 高,尤其是在移动设备。 低,在移动设备上,GrabPass虽然不会重新渲染场景,但要从CPU读取后备缓冲的数据,破坏了CPU和GPU的并行性,比较耗时。
自由度 高,虽然要重新渲染,但可以控制哪些进行渲染,分辨率大小等等。如最上面链接的游戏小地图制作。 低,获取的图形分辨率和屏幕一致。

除了上面两种方法,还可以使用命令缓冲(Command Buffers)实现抓取屏幕效果。见最上面链接。

作者:l773575310 发表于2017/11/21 11:12:57 原文链接
阅读:28 评论:0 查看评论

Unity Shader 学习笔记(17) 程序纹理(Procedural Texture)、程序材质(Procedural Materials)

$
0
0

Unity Shader 学习笔记(17) 程序纹理(Procedural Texture)、程序材质(Procedural Materials)

参考书籍:《Unity Shader 入门精要》
官网API:Texture2D
程序纹理:ProceduralTextureGeneration.cs


程序纹理

即由计算机生成的图像。通过脚本创建一个程序纹理,再赋给材质。

样例代码见上面链接。

  • Texture2D.SetPixel(x, y, color):设置像素的颜色。
  • Texture2D.Apply():在修改完纹理后需要应用才能生效。

程序材质

本质上和普通材质没有区别,区别在于纹理是程序纹理。创建于Substance Designer软件(纹理生成工具),功能非常强大。

作者:l773575310 发表于2017/11/21 11:15:46 原文链接
阅读:7 评论:0 查看评论

Python设计模式--适配器模式

$
0
0

说明

所谓适配器模式是指是一种接口适配技术,它可通过某个类来使用另一个接口与之不兼容的类,将一个类的借口转换成客户希望的另一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

简单实现

class Obj(object):
    def method(self):
        print 'obj'

class Obj2(object):
    def new_method(self):
        print 'obj2'

class Adpater(object):
    def __init__(self, adpatee):
        self.adpatee = adpatee

    def request(self):
        self.adpatee.new_method()

if __name__ == '__main__':
    objects = []
    a = Obj()
    b = Obj2()

    objects.append(a)
    objects.append(Adpater(b))

    for obj in objects:
        obj.method()  

更灵活实现

通过使用类的dict实现适配器模式

class Dog:
    def __init__(self, name):
        self.name = name

    def dog(self):
        print(self.name)


class Cat:
    def __init__(self, name):
        self.name = name

    def cat(self):
        print(self.name)


class Fish:
    def __init__(self, name):
        self.name = name

    def fish(self):
        print(self.name)


class Adapter:
    def __init__(self, obj, method):
        self.obj = obj
        self.__dict__.update(method)



if __name__ == "__main__":
    objects = []

    dog = Dog("dog")
    cat = Cat("cat")
    fish = Fish("dish")

    objects.append(Adapter(dog, dict(method=dog.dog)))
    objects.append(Adapter(dog, dict(method=cat.cat)))
    objects.append(Adapter(fish, dict(method=fish.fish)))

    for obj in objects:0
        obj.method()

应用场景

  • 重构代码统一调用
  • 增加需求不想改变原有代码
  • 对接其他project新增class

参考资料:

精通Python设计模式

作者:qq_29287973 发表于2017/11/21 11:58:41 原文链接
阅读:37 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live