黑马程序员技术交流社区

标题: 论面向对象编程的思考方式 [打印本页]

作者: 龙骑将杨影枫    时间: 2014-12-16 20:17
标题: 论面向对象编程的思考方式

面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。(from 百度百科)

题目:有100个人围成一个圈,从1开始报数,报到14的这个人就要退出。然后其他人重新开始,从1报数,到14退出。问:最后剩下的是100人中的第几个人?
相信不少人见过这个题目,论坛里也有人提出了自己的看法。

一个for循环巧妙解决约瑟夫环问题。
http://bbs.itheima.com/forum.php?mod=viewthread&tid=157633
(出处: 黑马程序员IT技术论坛)
这个帖子的效率最高,但是因为是递归算法,所以理解起来可能比较难。

从猴子选大王到约瑟夫环的经典问题
http://bbs.itheima.com/forum.php?mod=viewthread&tid=157626
(出处: 黑马程序员IT技术论坛)
这个帖子的易读性最好,虽然可能效率差了点,但是理解起来很简单。

事实上我写的程序思路和他一毛一样,很诚恳的说,甚至还要更臃肿一点。

我拿到题目,倒是没先动手写程序,先写了一个类。
具体来说,是一个person类。
因为第一眼看上去,我看到的是一个对象,100个人组成的1个环中,那个“人”的对象。
分析题干,我得出这么一个结论。100个人分成每一个人来说,每一个人的状态有2个:1是他此时的编号(100个里排第几),另一个是他此时的状态(圈内/被踢出去)。针对每一个人来说,他只有一个动作(被踢出圆环)。
那么,作为person类,应该这么写:
  1. package com.itheima.test10;

  2. public class Person {
  3.         public int num=0;//编号
  4.        
  5.         public boolean out=false;//队列状态

  6.         public Person(int i){
  7.                 this.num=i;
  8.         }
  9.        
  10.         //被踢出圈外
  11.         public void getOut(){
  12.                 this.out=true;
  13.         }
  14. }
复制代码

然后继续分析题干,找到了第二个对象:环。
那么这个环有什么呢?
有100个人。(废话)
除此之外,还有什么呢?
有三个过程:组成环、将人踢出环、踢完99个人以后输出最后剩下的那个人。
先说组成环的动作,最好的办法是用链表。因为链表很完美的阐述了“手拉着手”这个概念。(线性表也行)
但是我比较懒,就用数组了。
好了,100个人手拉手站好了。然后呢?然后当然是往外踢人了。
好吧,踢人是这么踢的:首先,一个人要报数。什么人报数呢?很简单,留在圈内的报数(out=false)。报完数干什么呢?下一个人报数。下一个人报的数比上1个人多1(自加)。
如果报数报到14,那么这个人被踢出去(执行getOut方法)。报数的重新从1开始报(注:因为我最开始设定的count=0,所以为了保证正确运行,所以用的++count。)
一直循环最后踢掉99个人,剩下1个人的时候,执行最后一步操作:输出。
那么输出的是什么呢?输出的是留在圈内的人。
思考结束,着手编写 环的类。
  1. package com.itheima.test10;

  2. public class Circle {
  3.         private Person[] circle=null;
  4.        
  5.         //首先,大家站好
  6.         public void init(int num){
  7.                 //初始化圆环,大家手拉手站成一排
  8.                 this.circle=new Person[num];
  9.                 for(int i=0;i<circle.length;i++)
  10.                         circle[i]=new Person(i+1);
  11.         }

  12.         //然后开始踢人
  13.         public  void kickOut(int num){
  14.                 int count=0;//初始化报数的数值
  15.                 int countTimes=this.circle.length-1;
  16.                 //进行circle长度-1次循环
  17.                 for(int i=countTimes;i>0;){
  18.                         for(int j=0;j<this.circle.length;j++){
  19.                                 Person p=circle[j];//循环到某个人
  20.                                 //对此人进行判断
  21.                                 if(!p.out)//如果其out值为false,换句话说没被踢出去
  22.                                         ++count;//报号的数字自增
  23.                                 if(count==num){//如果报道了某个人,报号到了num
  24. p.getOut();//执行此人的被踢出方法
  25.                                         count=0;//然后重新开始报号
  26.                                         i--;//踢出去一个人
  27.                         }
  28.                 }
  29.                 }
  30.         }
  31.        
  32.         //踢人完毕,输出最后剩下的数字
  33.         public void show(){
  34.                 for(int i=0;i<this.circle.length;i++){
  35.                         if(!this.circle[i].out){//最后没被踢出去的,就是留下来的
  36.                                 System.out.println("==>"+this.circle[i].num);
  37.                                 break;
  38.                                 }
  39.                 }
  40.         }
  41. }
复制代码
最后编写测试类:
  1. public class Demo {

  2.         public static void main(String[] args) {
  3.                 Circle cc=new Circle();
  4.                 cc.init(100);
  5.                 cc.kickOut(14);
  6.                 cc.show();
  7.         }

  8. }
复制代码
编程结束,运行demo输出的结果是92.











欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2