扎金花这种小游戏,我想作为一名程序员。大部分小时候都玩过吧!现在我们一起来看看搜狐这道面试题吧!看看如何用代码实现扎金花。


Q题目

事因

两个搜狐的程序员加了一个月班,终于放假了,于是他们决定扎金花渡过愉快的假期 。

游戏规则:

共52张普通牌,牌面为2,3,4,5,6,7,8,9,10,J,Q,K,A之一,大小递增,各四张; 每人抓三张牌。两人比较手中三张牌大小,大的人获胜。

对于牌型的规则如下:

  • 1.三张牌一样即为豹子

  • 2.三张牌相连为顺子(A23不算顺子)

  • 3.有且仅有两张牌一样为对子 豹子>顺子>对子>普通牌型 在牌型一样时,比较牌型数值大小(如AAA>KKK,QAK>534,QQ2>10104) 在二人均无特殊牌型时,依次比较三张牌中最大的。大的人获胜,如果最大的牌一样,则比较第二大,以此类推(如37K>89Q) 如二人牌面相同,则为平局。

输入描述:

输入两个字符串代表两个玩家的牌(如”10KQ” “354”),
先输入的作为玩家1,后输入的作为玩家2

输出描述:

 1 代表 玩家1赢     0 代表 平局   -1 代表 玩家2赢 -2 代表不合法的输入

输入例子:

KQ3 3Q9
10QA 6102
5810 7KK
632 74J
10102 K77
JKJ 926
68K 27A

输出例子:

1
1
-1
-1
1
1
-1

A解法

1.逻辑分析

  • (1)拿到玩家1和2输入的字符串,判断是否合法

  • (2)合法后,拆分字符串为字符串数组

  • (3)将字符串数组转化为int数组,并排序

  • (4)判断3张牌的相等情况

  • (5)比较大小,谁输谁赢

2.难点分析

  • 存在10时,字符串的拆分问题:可以根据字符串长度来判断拆分

  • 将字母转为数字:先将拿到的字符串都转为大写,这样小写和大写字母都一样了,然后直接用if判断return就可以了

  • 比较谁输谁赢:采用从大到小的方式比较,先判断是否有豹子,在判断顺子,再判断对子,最后判断无牌型的

  • 对顺子的处理问题

3.代码实现

package 搜狐面试2016;import java.util.Arrays;
import java.util.Scanner;public class Test1 {public static void main(String[] args) {// 2,3,4,5,6,7,8,9,10,J,Q,K,AScanner scanner = new Scanner(System.in);boolean isContinue=true;while (isContinue) {//1.游戏规则System.out.println("游戏规则:共52张普通牌,牌面为2,3,4,5,6,7,8,9,10,J,Q,K,A之一,大小递增,各四张; 每人抓三张牌。两人比较手中三张牌大小,大的人获胜。");System.out.println("对于牌型的规则如下:");System.out.println("1.三张牌一样即为豹子");System.out.println("2.三张牌相连为顺子(A23不算顺子)");System.out.println("3.有且仅有两张牌一样为对子 豹子>顺子>对子>普通牌型 在牌型一样时,比较牌型数值大小");System.out.println("谁输谁赢:1 --代表玩家1赢;0 --代表 平局   ;-1 --代表玩家2赢 ;-2 --代表不合法的输入");//2.分别出牌System.out.println("请玩家1出牌:");String num1 = scanner.next();System.out.println("请玩家2出牌:");String num2 = scanner.next();//3.判断是否合法boolean flag=isValid(num1, num2);if(!flag){//不合法System.out.println("-2");}else {//输入合法---先拆分字符串---再转化为int数组//4.拆分字符串String[] nums1=getStrArray(num1);String[] nums2=getStrArray(num2);System.out.println("拆分后的字符串数组A:"+Arrays.toString(nums1));System.out.println("拆分后的字符串数组B:"+Arrays.toString(nums2));//5.转化为int数组int[] nums11=strToNumber(nums1);int[] nums22=strToNumber(nums2);System.out.println("转化为int后的数组A:"+Arrays.toString(nums11));System.out.println("转化为int后的数组B:"+Arrays.toString(nums22));//6.获得三张牌的相等情况int[] equalNum11=equalNum(nums11);int[] equalNum22=equalNum(nums22);System.out.println("三张牌的相等情况--数组A:"+Arrays.toString(equalNum11));System.out.println("三张牌的相等情况--数组B:"+Arrays.toString(equalNum22));//7.判断输赢int whoWin=whoWin(equalNum11, nums11, equalNum22, nums22);System.out.println(""+whoWin);}//是否继续System.out.println("是否继续?输入N或n退出,其他任意键继续!");String string = scanner.next();string=string.toUpperCase();if("N".equals(string)){isContinue=false;}}}/*1.判断输入的内容是否合法*          不合法两种情况:(1)出现的字符不是2,3,4,5,6,7,8,9,10,J,Q,K,A(2)每种牌只有4张,超过4张则不合法了*方法说明:*该方法只处理情况(1),情况(2)放在判断输赢的时候处理,因为第二种情况涉及牌面转化后计算的问题*/public static boolean isValid(String num1, String num2) {String reg = "([2-9JQKA]|10){3}";// 正则匹配,只能出现2,3,4,5,6,7,8,9,10,J,Q,K,A,并且一共只能出现3次boolean a = num1.matches(reg);boolean b = num2.matches(reg);// 有一方不合法就返回falseif (a == false || b == false) {return false;} else {// 都合法return true;}}// 1.拆分字符串,得到三个数字public static String[] getStrArray(String num) {// 字符串的长度和拆分后的数组int length = num.length();String[] nums = new String[3];// 无论输入的J,Q,K,A是否为大写,都改为大写num.toUpperCase();// 字符串不含10时,长度都为3if (length == 3) {// nums=num.split("");//使用该方法拆分会多出一个空格位--比如33a-->[,3,3,1]for (int i = 0; i < nums.length; i++) {nums[i] = num.substring(i, i + 1);}} else if (length == 4) {// 字符串含一个10int index = num.indexOf("1");// 10在首位:10XXif (index == 0) {nums[0] = "10";nums[1] = num.substring(2, 3);nums[2] = num.substring(3);} else if (index == 1) {// 10在中位:X10Xnums[0] = num.substring(0, 1);nums[1] = "10";nums[2] = num.substring(3);} else {// 10在末位:XX10nums[0] = num.substring(0, 1);nums[1] = num.substring(1, 2);nums[2] = "10";}} else if (length == 5) {// 字符串2个10----1010X 或 10X10 或 X1010int first = num.indexOf("1");// 第一个10int second = num.lastIndexOf("1");// 第二个10int cha = second - first;// 两个1距离大于2时,说明X在中间if (cha > 2) {nums[0] = nums[2] = "10";nums[1] = num.substring(2, 3);} else {// 两个1距离等于2时,说明两个10是挨在一起的if (first == 0) {nums[0] = nums[1] = "10";nums[2] = num.substring(4);} else {nums[0] = num.substring(0, 1);nums[1] = nums[2] = "10";}}} else {// 字符串为3个10for (int i = 0; i < nums.length; i++) {nums[i] = "10";}}return nums;}// 2.将字符串数组转为int数组public static int[] strToNumber(String[] nums) {int[] arr = new int[3];for (int i = 0; i < nums.length; i++) {arr[i] = letterToNumber(nums[i]);}Arrays.sort(arr);return arr;}/** 3.比较拆分后的三个数字相等情况,并返回数组--[参数1,参数2] * * 参数1:数字相同的个数;* 参数2:若有相同数字,参数2表示相同的是哪个数字;-------此时参数2只可能为2-14中的一个 *      若没有相同数字--参数2表示是否有顺子--有顺子为1,没顺子为0----此时参数2只可能是0或1* * 例如: * 若有两个相同,则返回[2,相同的数字]; * 若三个都相同,则返回[3,相同的数字];* 若三个数字都不同,且不是顺子,则返回[0,0];若是顺子则返回[0,1]*/public static int[] equalNum(int[] nums) {int[] arr = new int[2];// 判断相等的个数if (nums[0] == nums[1] && nums[0] == nums[2]) {// 三个数相等arr[0] = 3;arr[1] = nums[0];} else if (nums[0] != nums[1] && nums[0] != nums[2] && nums[1] != nums[2]) {// 三个数均不相等--此时有一个顺子的问题要处理arr[0] = 0;// 因为A23不算顺子,所以只能出现2-14间的顺子,即234,345,...,121314// 此时相邻两个数差为1if (nums[1] - nums[0] == 1 && nums[2] - nums[1] == 1) {// 为顺子arr[1] = 1;} else {arr[1] = 0;}} else {// 两个数相等arr[0] = 2;// 若数组中两个数差值为0,说明就是这个数为对子if(nums[0]-nums[1]==0){arr[1]=nums[0];}else if (nums[0]-nums[2]==0) {arr[1]=nums[0];}else {arr[1]=nums[2];}}return arr;}/** 4.判断谁输谁赢 参数说明:a,primaryA--玩家1 b,primaryB--玩家2* * 参数a,b:判断数字相等情况后返回的数组----即方法isEqual()处理后的结果* 参数primaryA,primaryB:原始数组(备注:转化为int后的数组---即方法strToNumber()处理后的结果)* * * 备注:该方法太长,可以将豹子,顺子,对子,普通牌型分别提取为一个方法*     那么需要再创建一个方法用于判断玩家1和2的牌中出现是豹子,顺子,对子,普通牌型中的哪一种*     将返回值做为if的条件,再分别去调用对应的豹子,顺子,对子,普通牌型方法*     *     因为这样方法太多,笔者就不单独提出来封装了*/public static int whoWin(int[] a, int[] primaryA, int[] b, int[] primaryB) {// 1)判断是否为豹子if (a[0] == 3 && b[0] == 3) {// 都是豹子则比大小if (a[1] > b[1]) {return 1;} else if (a[1] < b[1]) {return -1;} else {// 玩家1和2豹子相同是不可能的,每种牌只有4张return -2;}} else if (a[0] == 3 && b[0] != 3) {// 只有玩家1是豹子--处理可能出现5张相同牌的情况--需要判断玩家2是否有对子,有,那么是否与豹子是相同的牌// 玩家2有对子,并且与玩家1的豹子牌面相同if (b[0] == 2 && a[1] == b[1]) {return -2;}return 1;} else if (a[0] != 3 && b[0] == 3) {// 只有玩家2是豹子--同理上面// 玩家1有对子,并且与玩家2的豹子牌面相同if (a[0] == 2 && a[1] == b[1]) {return -2;}return -1;} else {// 2)都没豹子,判断是否为顺子--利用非顺子时a[1]和b[1]不可能出现1,只会为2-14if (a[1] == 1 && b[1] == 1) {// 都为顺子,则比大小--因为是顺子,所以比较第一个数值即可if (primaryA[0] > primaryB[0]) {return 1;} else if (primaryA[0] < primaryB[0]) {return -1;} else {return 0;}} else if (a[1] == 1 && b[1] != 1) {// 只有玩家1是顺子return 1;} else if (a[1] != 1 && b[1] == 1) {// 只有玩家2是顺子return -1;} else {// 3)都不是顺子,判断是否有对子if (a[0] == 2 && b[0] == 2) {// 都有对对子,则比大小if (a[1] > b[1]) {return 1;} else if (a[1] < b[1]) {return -1;} else {// 对子相同,则比较单个的那个数int thirdA = 0;// 玩家1,单独的牌int thirdB = 0;// 玩家2,单独的牌for (int i = 0; i < primaryA.length; i++) {if (primaryA[i] != a[1]) {thirdA = primaryA[i];}if (primaryB[i] != b[1]) {thirdB = primaryB[i];}}// 比较单个数字if (thirdA > thirdB) {return 1;} else if (thirdA < thirdB) {return -1;} else {return 0;}}} else if (a[0] == 2 && b[0] != 2) {// 只有玩家1有对子return 1;} else if (a[0] != 2 && b[0] == 2) {// 只有玩家2有对子return -1;} else {// 4)都没豹子,顺子,对子,直接比大小if (primaryA[2] > primaryB[2]) {return 1;} else if (primaryA[2] < primaryB[2]) {return -1;} else {// 最大值相等,比较第二大的if (primaryA[1] > primaryB[1]) {return 1;} else if (primaryA[1] < primaryB[1]) {return -1;} else {// 最大值和第二大值都相等if (primaryA[0] > primaryB[0]) {return 1;} else if (primaryA[0] < primaryB[0]) {return -1;} else {return 0;}}}}}}}// 5.将字符转为数字----------将非数字的J,Q,K,A转换为数字11,12,13,14--并将本身数字的字符串转为int类型public static int letterToNumber(String letter) {if (letter.equals("J")) {return 11;} else if (letter.equals("Q")) {return 12;} else if (letter.equals("K")) {return 13;} else if (letter.equals("A")) {return 14;}return Integer.parseInt(letter);}
}

运行测试

长度不合法

单个牌6出现了5次,不合法

豹子

顺子和对子

都是字母,顺子和对子

出现10,两个顺子

都无牌型,直接比大小

算法--2016搜狐面试:搜狐员工放假了,都玩什么?相关推荐

  1. 新浪搜狐网易等那些老牌互联网公司 现在都怎样了?

    新浪搜狐网易等那些老牌互联网公司 现在都怎样了? 王利阳 11月14日 08:27 新浪 搜狐 网易 分类 :互联网 阅读:26541 评论:2 对互联网企业来说,十年可以改变很多,可以改变人们的上网 ...

  2. 图 相关算法~从头学算法【广搜、 深搜、 拓扑排序、 并查集、 弗洛伊德算法、迪杰斯特拉算法】

    图的相关主流算法主要有: 广度优先搜索 深度优先搜索 拓扑排序 并查集 多源最短路径(弗洛伊德算法) 单源最短路径(迪杰斯特拉算法) 其中呢,最基本的是前两种,也就是平时常用的广搜和深搜,本文中将概要 ...

  3. [ NOIP提高组 2016]愤怒的小鸟(暴搜 + 状压DP)// [SNOI2017]一个简单的询问(莫队)

    一次性写两道题 T1:一个简单的询问 题目 题解 代码实现 T2:愤怒的小鸟 题目 暴搜题解 暴搜代码实现 状压DP题解 状压DP代码实现 T1:一个简单的询问 题目 给你一个长度为 N 的序列 ai ...

  4. 回客科技 面试的 实现ioc 容器用到的技术,简述BeanFactory的实现原理,大搜车面试的 spring 怎么实现的依赖注入(DI)...

    前言:这几天的面试,感觉自己对spring 的整个掌握还是很薄弱.所以需要继续加强. 这里说明一下spring的这几个面试题,但是实际的感觉还是不对的,这种问题我认为需要真正读了spring的源码后说 ...

  5. 算法——广搜(BFS)/深搜(DFS)

        在图的基本算法中,最初接触的就是图的遍历算法,根据访问节点的顺序,可分为广度优先搜索(BFS)和深度优先搜索(DFS). 广度优先搜索 广度优先搜索算法主要解决两个问题: 从节点A出发有到节点 ...

  6. 腾讯实习生面试2016两道面试题目?(知乎)

    腾讯实习生面试2016两道面试题目?修改 谢谢大神们高质量的回答,满满干货,excited ------------------------------------------------------ ...

  7. 2020最新-精选基础算法100题(面试必备)

    0x01.概述 作为一个程序员,算法能力必不可少,虽然不一定是算法工程师,但是算法还是彰显着个人的编码能力,面试中也经常会被问到,甚至会被要求临场做算法题,所以,还是好好积累吧. 个人其实对算法挺有兴 ...

  8. Go 分布式学习利器(15) -- Go 实现 深搜和广搜

    强化语法,回顾算法. 通过Go语言实现 深度优先搜索 和 广度优先搜索,来查找社交网络中的三度好友关系(三度指的是一个节点到 其相邻节点 到 其相邻节点的节点 ,图递增三层好友关系). 涉及到的Go语 ...

  9. 2016腾讯面试经验

    [实习面试]阿里&腾讯offer的点点滴滴(内附干货)2016 前言: - 4月8号下午6点,突然接到腾讯hr的电话,本来已经不抱希望的我一脸懵逼,差点连自我介绍都不会说了.之所以不抱希望,是 ...

最新文章

  1. Dell服务器的 Idrac调试口的配置方式
  2. IDA执行python脚本文件,python编辑器的操作
  3. java 判断语句 性能_前端性能优化:js中优化条件判断语句
  4. Git多人协作工作流程
  5. 数值传热学陶文铨pdf_西安交大陶文铨当选“2019最美科技工作者”
  6. Java学习之文件操作
  7. 做基础产品的体会【转载】
  8. pytorch学习笔记(九):softmax回归的简洁实现
  9. 11gR2 Grid Infrastructure Installation prerequisites On LINUX
  10. To be a tough man
  11. 项目中用到的ws2811炫彩灯控制程序
  12. 通过代理上网,如何配置Outlook
  13. react动态添加背景图片/不同内容添加对应背景
  14. [转载]前端代码规范 及 最佳实践
  15. 注册用户数破亿 平安金管家APP成全球寿险首个过亿应用
  16. 攻防世界逆向高手题之dmd-50
  17. windows设置开机启动程序
  18. verilog 实现9位有符号乘法器
  19. 华为手表 GT3训练计划怎么用?
  20. 来去之间:微博第四季度净营收4.819亿美元 同比增长28%

热门文章

  1. 人工智能到底是什么?人工智能如何改变社会?中国的人工智能应该做怎样的探索?
  2. 比特币钱包(3) BIP32 HD钱包之密钥树
  3. [密码学] 杂凑函数
  4. Linux常用的基本命令cp、mv、rm、cat、find(三)
  5. 02-缓存一致性---实现big.LITTLE、GPU 计算和企业应用
  6. [ARM-assembly]-ARM交叉编译器下编译的各个镜像的反汇编文件分析
  7. Python正则表达式之额外补充(7)
  8. project1两周收获总结
  9. WebLogic CVE-2021-2394 RCE 漏洞分析
  10. 【Linux】 iptables vs firewalld