算法第四版练习题:热还是冷

题目描述是要猜出1~N之间的一个秘密整数。每次猜测之后,如果相等则游戏结束,否则会得知和上一次猜测相比是更加接近(热)还是远离(冷)。

我的思路是利用二分的思想,将秘密数的区间范围从1~N逐渐缩小直到找到。
记录下代码:

/*
热还是冷?
随机生成一个1~N的整数:秘密数,猜测它,如果猜对则结束
相较于上一次猜测,更接近或不变时为热,否则为冷
 */

import edu.princeton.cs.algs4.*;
import java.lang.Math;

class HotColdGame {
    public final int N = 2000;  // 范围
    private int secret; // 秘密数
    private int diff;   //上一次猜测的差距
    HotColdGame() {
        secret = StdRandom.uniform(1, 2000);
        diff = Integer.MAX_VALUE;
    }
    // 如果热,返回1;冷返回-1;猜对返回0
    public int guess(int suppose) {
        if (suppose == secret)
            return 0;
        // 本次猜测的差距
        int temp = Math.abs(suppose - secret);
        if (temp > diff) {
            diff = temp;
            return -1;
        }
        else {
            diff = temp;
            return 1;
        }
    }
    // 自己猜
    public void play() {
        diff = Integer.MAX_VALUE;
        StdOut.println("guess a int number from 1 ~ "+ N);
        // 并没有做其他鲁棒性完善
        StdOut.println("If you want to quit, just input -1");
        int suppose = StdIn.readInt();
        while (true) {
            if (suppose == -1) {
                StdOut.println("What a pity~");
                return;
            }
            int flag = guess(suppose);
            if (flag == 0)
                break;
            else if (flag == -1)
                StdOut.print("Cold!");
            else
                StdOut.print("Hot!");
            StdOut.println("\t Continue!");
            suppose = StdIn.readInt();
        }
        StdOut.println("done! The secret is " + secret);
    }
    // 程序猜
    public void autoGuess(int lo, int hi) {
        diff = Integer.MAX_VALUE;
        // 将区间均分,猜两次
        int flag;
        // 为了让程序的猜测更加随机,没有严格二分,而是随机生成值。
        // 第一次在左半区间随机生成一个值
        int first = StdRandom.uniform(lo, (hi - lo) / 2 + lo);
        flag = guess(first);
        if (flag == 0) {
            StdOut.println("done! The secret is " + first);
            return;
        }
        else if (flag == 1)
            StdOut.println(first + " Hot!");
        else
            StdOut.println(first + " Cold!");

        // 第二次在右半区间随机生成一个值
        int second = StdRandom.uniform((hi - lo) / 2 + lo, hi);
        flag = guess(second);
        int mid = (second - first) / 2 + first; // 两次猜测的中间值
        if (flag == 0) {
            StdOut.println("done! The secret is " + second);
            return;
        }
        // 第二次猜测比第一次猜测热,说明更靠近右半区间,即区间更新为(mid, hi)
        else if (flag == 1) {
            StdOut.println(second + " Hot!");
            autoGuess(mid, hi);
        }
        // 同理
        else {
            StdOut.println(second + " Cold!");
            autoGuess(lo, mid);
        }
    }
}

public class HotOrCold {
    public static void main(String[] args) {
        HotColdGame game = new HotColdGame();
        game.play();
        StdOut.println();
        game.autoGuess(1, game.N);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值