刚开始学习C语言的时候,常常听到前辈说,C语言的核心就是算法。但是对于小白来说,常常一脸懵逼,搞不懂啥叫算法?算法有什么用?我的if-else语句照样可以走天下。但是作为小白来说虽然不懂但是也不敢问,只能把这个疑问消灭在萌芽状态。

  那么算法到底意味着什么?为什么算法如此重要,那么今天就通过一个简单的石头剪刀布的游戏来粗略的谈一下算法的形成原因和作用?

  比如现在要写一个两个人玩石头剪刀布的程序,要如何实现。对于小白来说,这简单if-else语句就搞定了。

代码如下:

if(自己==石头 && 对方==石头) 平局;
else if(自己==石头 && 对方==剪刀) 自己赢;
else if(自己==石头 && 对方==布) 对方赢;

if(自己==剪刀 && 对方==石头) 对方赢;
else if(自己==剪刀 && 对方==剪刀) 平局;
else if(自己==剪刀 && 对方==布) 自己赢;

if(自己==布 && 对方==石头) 自己赢;
else if(自己==布 && 对方==剪刀) 对方赢;
else if(自己==布 && 对方==布) 平局;

当然这个代码还可以优化一下

if(自己==石头)
{
    if(对方==石头) 平局;
    else if(对方==剪刀) 自己赢;
    else if(对方==布) 对方赢;
}

if(自己==剪刀)
{
    if(对方==石头) 对方赢;
    else if(对方==剪刀) 平局;
    else if(对方==布) 自己赢;
}

if(自己==布)
{
    if(对方==石头) 自己赢;
    else if(对方==剪刀) 对方赢;
    else if(对方==布) 平局;
}

    这个结构看起来更加清晰明了,也可以使用switch语句来实现,不管用什么语句来实现,这里核心思想就是将所有的情况列出来,然后逐一去判断,没有任何算法可言。如果按照这个思路去实现,那么假如要比较的是几十种情况,难道还能逐一去列举判断吗?那几千种几万种比较呢?光列举出所有的情况估计都要累死了。

    那么这个时候就需要用一个方法来抽象这种情况,让程序判断起来更加方便。逻辑上更容易实现。石头剪刀布的核心类似于比较大小,那么能不能将石头剪刀布转换为数字大小的比较。

   这里假设 石头 = 3  剪刀 = 2 布 = 1 ,然后将石头剪刀布的逻辑转换为 数字  石头 >  剪刀  对应 3 > 2,  剪刀 > 布 对应  2 > 1, 布 > 石头 对应 1 > 3, 显然前两个逻辑成立,最后一个逻辑不成立,

那么就不能直接通过比较大小来判断,通过观察发现,凡是逻辑成立的两个数字之间相差1,最后一个逻辑不成立,数字之间相差2。那么是否可以将比较大小转换为数学的减法运算。

当自己的数字 - 对方的数字 结果等于1时,自己获胜。结果等于2时,对方获胜,结果等于0时,平局。这样分析之后貌似可以实现。那么将所有的情况转换为用减法来实现时时代码逻辑如下:

石头 = 3  剪刀 = 2 布 = 1 

if(自己==石头 && 对方==石头) 平局;          对应算式为 3-3 = 0
else if(自己==石头 && 对方==剪刀) 自己赢;    对应算式为 3-1 = 1
else if(自己==石头 && 对方==布) 对方赢;      对应算式为 3-1 = 2

if(自己==剪刀 && 对方==石头) 对方赢;        对应算式为 2-3 = -1
else if(自己==剪刀 && 对方==剪刀) 平局;      对应算式为 2-2 = 0
else if(自己==剪刀 && 对方==布) 自己赢;      对应算式为 2-1 = 1

if(自己==布 && 对方==石头) 自己赢;         对应算式为 1-3 = -2
else if(自己==布 && 对方==剪刀) 对方赢;     对应算式为 1-2 = -1
else if(自己==布 && 对方==布) 平局;        对应算式为 1-1 = 0

通过对比算式的结果可以发现   当自己 - 对方的结果等于0时为平局,自己 - 对方的结果为1或者-2时 自己赢。当自己 - 对方的结果为2或者-1 时对方的赢。

那个根据这个就可以将上面的算法抽象为3类,自己赢,平局,对方赢。这样代码实现起来就更加简洁了,实现方法如下

/* 石头 = 3  剪刀 = 2 布 = 1  */

结果 =  自己 - 对方;

if(结果 == 0)  平局;
else if(结果 == 1 || 结果 == -2) 自己赢;
else if(结果 == -1 || 结果 == 2) 对方赢 ;

这样直接通过3条语句就直接实现了石头剪刀布的逻辑判断,而且程序写起来更加的简洁,逻辑更加清晰。可见在代码逻辑实现的过程中有了算法的加持,程序发生了质的变化。

一个简单的例子就可以看出算法在程序中举足轻重的作用,所以说写代码不仅仅上是逻辑上把功能实现了就可以了,但实现功能的同时,还需要考虑效率的问题。

下面在举一个简单的例子来演示一下算法的应用。

      这里有15瓶水,其中有1瓶是剧毒,小白鼠只要喝上一滴,过一天后就会死亡,那么如何用最少的小白鼠,在最短的时间内找出哪个瓶子里面有毒药?

      直接可以想到的办法就是找15只小白鼠,一只小白鼠喝对应编号的一瓶水就行。这种方法虽然最简单,但是浪费的小白鼠却是最多的。肯定不是最好的办法。可以让一个小白鼠喝好几个瓶子的水,然后通过交叉排除的方法筛选出来那个瓶子有毒。这个可以通过二进制的思维来实现。

     首先将这15个瓶子标上号码,从1到15,然后将这些数字转换为二进制。

                               

剪刀石头布 java 剪刀石头布怎样赢_石头

   

可以看到15个瓶子,通过二进制数表示的话,需要4位,那么1只小白鼠代表1位的话,用4个小白鼠就可以表示1---15,顺着这个思路就可以通过一个小白鼠喝好几瓶混合的水,来筛选出有毒的那瓶水。

剪刀石头布 java 剪刀石头布怎样赢_算法_02

将15瓶水分为4组,第一组黄色的就是二进制数最低位为1的编号,也就是将二进制字最右边那个数字为1对应的那瓶水混合在一起,然后将混合后的水给第1只小白鼠喝。

相当于第一只小白鼠喝的是1、3、5、7、9、11、13、15这几个编号混合起来的水,按照同样的方法,将二进制数字右边第二位为1的水混合起来,给第二只小白鼠喝。

相当于第二只小白鼠喝的是2、3、6、7、10、11、14、15这几个编号混合起来的水,按照同样的方法,将二进制数字左边第二位为1的水混合起来,给第三只小白鼠喝。

相当于第三只小白鼠喝的是4、5、6、7、12、13、14、15这几个编号混合起来的水,按照同样的方法,将二进制数字最左边为1的水混合起来,给第四只小白鼠喝。

相当于第四只小白鼠喝的是8、9、10、11、12、13、14、15这几个编号混合起来的水。

第一天将这些混合起来的水,分别给四只小白鼠喝,然后第二天观察结果就可以知道哪瓶水有毒了?

假如第二天,第一只和第三只小白鼠死了,说明对应的二进制数字第一位和第三位是1,对应的二进制数字就是 0101,这样就可以根据二进制数直接算出来有毒的是5号瓶。

假如第二天,1、3、4只小白鼠死了,说明对应的二进制数字就是1101,那么瓶子对应的编号就是13号。

这样用4只小白鼠,在第二天就可以找出有毒的那瓶水了。

通过转换一个思维,用另一种方法去解决问题,就可以轻松的将复杂的问题简单化,可以看出一个好多算法在实际应用中可以起到一两拨千金的作用。