让计算机来做猜数字

import java.io.*;

//package com.maodajun.javaeye2;

public class GuessNumber2
{
  public static void main(String[] argv) throws Exception
  {
    GuessNum gn = new GuessNum();
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "GBK"));
    int i = 1;
    while (true) {
      String guessSeed = gn.getNextSeed();
      if (guessSeed.startsWith("我猜") || guessSeed.startsWith("你是")) {
        System.out.println(guessSeed);
        System.exit(0);
      }

      System.out.println();
      System.out.println("我第" + (i++) +"次猜,这个数是" + guessSeed);
      System.out.println("请你说位置及值都对的有几个?");
      String s = br.readLine();
      int a = Integer.parseInt(s);
      if (a == 4) {
        System.out.println("我猜对了吧,哈哈哈!!!");
        System.exit(0);
      }
      System.out.println("请你说值对但位置不对的有几个?");
      s = br.readLine();
      int b = Integer.parseInt(s);
      gn.setGuessReuslt(a, b);
    }
  }
}

class GuessNum
{
  boolean[] isValid; //是否有可能,为false时为不可能,true继续排除
  int[] nums; //所有可能值,共5040 * 4长,每四个作一个可能值,上面的isValid记录这5040个可能性是否还有可能
  int a, b, c, d; //上次猜测值,暂存

  public GuessNum()
  {
    isValid = new boolean[5040];
    java.util.Arrays.fill(isValid, true); //刚开始时全有可能
    nums = new int[5040 * 4];
    int pos = 0; //5040   *   4数组中的位置

    //初始化,把所有可能值的a,   b,   c,   d位全按四个一组放入nums中
    for (int a = 0; a < 10; a++) {
      for (int b = 0; b < 10; b++) {
        if (a == b)
          continue;
        for (int c = 0; c < 10; c++) {
          if (a == c || b == c)
            continue;
          for (int d = 0; d < 10; d++) {
            if (a == d || b == d || c == d)
              continue;
            nums[pos++] = a;
            nums[pos++] = b;
            nums[pos++] = c;
            nums[pos++] = d;
          }
        }
      }
    }
  }

  /**
   *   得到下一个猜测目标,如果没有了可能性,证明操作者前面输入错误,如果可能性只有一,立即确定
   *   @return
   */
  public String getNextSeed()
  {
    int others = 0;
    int pos = 0;
    for (int i = 0; i < 5040; i++) {
      if (isValid[i]) {
        if (others > 0) {
          others++;
          //break;
        }
        else {
          others++;
          pos = i;
        }
      }
    }
    System.out.println("还剩"+others+"个满足条件的数");

    if (others == 0) {
      return "你是个赖皮狗,前面你回答错了,查查吧";
    }

    if (others == 1) {
      int i = pos * 4;
      return "我猜这个数一定是" + nums[i++] + nums[i++] + nums[i++] + nums[i++];
    }

    for (int i = 0; i < 5040; i++) {
      if (isValid[i]) {
        i *= 4;
        a = nums[i];
        b = nums[i + 1];
        c = nums[i + 2];
        d = nums[i + 3];
        return new StringBuffer().append(nums[i++]).append(nums[i++]).append(
            nums[i++]).append(nums[i++]).toString();
      }
    }

    //理论上不可能到这一步
    throw new RuntimeException("你是个赖皮狗,前面你回答错了,查查吧");
  }

  //设置操作者的反馈(x   个   a,   y   个   b)
  public void setGuessReuslt(int x, int y)
  {
//    if (x == 4) {
//      return;
//    }
    for (int pos = 0; pos < 5040; pos++) {
      if (!isValid[pos])
        continue;
      int numspos = pos * 4;
      if (getMyX(pos) != x) {
        isValid[pos] = false;
        continue;
      }
      if (getMyY(pos) != y) {
        isValid[pos] = false;
        continue;
      }
    }
  }

  //测试,把每个可能值都与上次猜测值比较,就会得到这个可能值与猜测值是几个a的关系
  private int getMyX(int pos)
  {
    int myx = 0;
    pos *= 4;
    if (nums[pos++] == a)
      myx++;
    if (nums[pos++] == b)
      myx++;
    if (nums[pos++] == c)
      myx++;
    if (nums[pos++] == d)
      myx++;
    return myx;
  }

  //测试,把每个可能值都与上次猜测值比较,就会得到这个可能值与猜测值是几个b的关系
  private int getMyY(int pos)
  {
    int myy = 0;
    pos *= 4;
    if (nums[pos] == b || nums[pos] == c || nums[pos] == d)
      myy++;
    if (nums[pos + 1] == a || nums[pos + 1] == c || nums[pos + 1] == d)
      myy++;
    if (nums[pos + 2] == a || nums[pos + 2] == b || nums[pos + 2] == d)
      myy++;
    if (nums[pos + 3] == a || nums[pos + 3] == b || nums[pos + 3] == c)
      myy++;
    return myy;
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值