《编程之美》——游戏之美——中国象棋将帅问题——tip

本文探讨了在单片机编程中使用位操作解决实际问题的方法,特别是针对中国象棋中将帅问题的一种高效解决方案。通过对位操作、位段及数学方法的应用,实现了仅用一个变量来表示两个棋子的位置,同时确保了程序的简洁性和计算效率。
摘要由CSDN通过智能技术生成

 《编程之美》——游戏之美——中国象棋将帅问题——tip
拿到新书,很高兴,虽然因为雪的缘故迟到了几天。
关于这个将帅的问题,也是关于这个只能使用一个变量的问题。
关于第一个问题,就是将帅不能见面的问题,可以用==来判断。
关于第二个问题,倒是觉得挺好玩的。
搞单片机上来的都习惯用位来解决问题,有时候我也老是把变量当成寄存器中的位来用。
当然,用结构体来实现寄存器组的方法也是跟uboot学来的。
对书中给出的第一种解法,看到了无数的位移操作,想起了用AVR的时候……
对于书中给出的第三种解法,在某牛人的单片机头文件里看到过位段,
但是记得好像在哪里看到不推荐使用位段了,感觉位段就是个MINI类结构体……
对于书中给出的第二种解法,一看上去,知道是用了数学的东西来手段了一下数字。
然后,抽时间研究了一小下,记录在此,还望各位大牛不要拍砖。^^。

AB都有9种可能,因此9*9=81,所以,定义了这个i是81,用排列组合的知识想一下,的确是有81种可能。
次数不是很多,穷举出来了。
然后看到了/和%符号,一个是除法,一个是取模。取模还是在初中暑假里学到的……,貌似……。
也就是说,算法当中用到了商和余数,来作为一些限制条件的数据。
之所以是9,是因为有9个位置;
之所以是3,因为横竖3行3列。
然后,觉得脑子不够用的,于是直接printf一些数据出来,直观的分析一下商和余数之间的关系。
虽然……这个问题貌似小学的小朋友们已经研究过了。
i/9是取商,i%9是取余数,对于每一次取商,都会把从0到i-1取一遍。
从而形成了两个循环:
for ( i = 0 ; i < 商 ; i++) {
    for ( j = 0 ; j < 余数 ; j++ ) {
        ;
    }
}
至于后面的%3,是为了取3行3列,把数限制在3以内。
取余数的好处还是比较多的,常常可以把一个很大的数,限制在一个小范围内循环。
根据穷举的思想,也就是要挨个遍历,因此用到了循环。
for ( i = 0 ; i < n ; i++) {
    for ( j = 0 ; j < n ; j++ ) {
        ;
    }
}
然后把i j n都想办法用一个变量来表示~~。
然后,我就研究了一下关于n=i*j的问题。
在这种情况下
i=n/j    i=n%i
j=n/i    j=n%j
虽然……道理比较简单吧,一般都是用在数学上貌似。
(i*j)/j 商i 余j.(i*j)/i 商j 余i.
OK,基本上也就是这么回事。
然后想,为啥非要用一个变量呢。
莫不成是,用一个变量比用三个变量要少占存储空间,更多的利用CPU的寄存器来完成计算?
貌似把1个变量和3个变量的代码反汇编看一下能知道一些问题。
一个程序A:用i=81+while(i--),另一个程序B:用i=0,j=0+双for循环。
然后直接gcc file.c 生成a.out,然后用objdump a.out -d > file 中。(我不会用VC……)
然后,比较两个文件大小,它们的<main>差了39行,结果是B程序要少,A程序要多。
难不成说是多定义了变量还用了for的,生成的汇编代码反而小一些。执行起来理论上快那么一点。
为什么?这个就不清楚了,我对看汇编代码还是比较头疼的。
貌似能用的寄存器也就EA EB EC ED这么几个……,比ARM架构的r0~r15要少很多~~。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值