目录
Q题目
事因
游戏规则:
对于牌型的规则如下:
输入描述:
输出描述:
输入例子:
输出例子:
A解法
1.逻辑分析
2.难点分析
3.代码实现
运行测试
首页 Java java教程 如何用代码实现扎金花游戏

如何用代码实现扎金花游戏

Jun 26, 2017 pm 02:10 PM
员工 搜狐 算法 面试

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


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,A
        Scanner 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);

        // 有一方不合法就返回false
        if (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时,长度都为3
        if (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) {
            // 字符串含一个10
            int index = num.indexOf("1");

            // 10在首位:10XX
            if (index == 0) {
                nums[0] = "10";
                nums[1] = num.substring(2, 3);
                nums[2] = num.substring(3);
            } else if (index == 1) {
                // 10在中位:X10X
                nums[0] = num.substring(0, 1);
                nums[1] = "10";
                nums[2] = num.substring(3);
            } else {
                // 10在末位:XX10
                nums[0] = num.substring(0, 1);
                nums[1] = num.substring(1, 2);
                nums[2] = "10";
            }
        } else if (length == 5) {
            // 字符串2个10----1010X 或 10X10 或 X1010
            int first = num.indexOf("1");// 第一个10
            int second = num.lastIndexOf("1");// 第二个10
            int 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个10
            for (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
            // 此时相邻两个数差为1
            if (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-14
            if (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,两个顺子
这里写图片描述

都无牌型,直接比大小
这里写图片描述

以上是如何用代码实现扎金花游戏的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

CLIP-BEVFormer:显式监督BEVFormer结构,提升长尾检测性能 CLIP-BEVFormer:显式监督BEVFormer结构,提升长尾检测性能 Mar 26, 2024 pm 12:41 PM

写在前面&笔者的个人理解目前,在整个自动驾驶系统当中,感知模块扮演了其中至关重要的角色,行驶在道路上的自动驾驶车辆只有通过感知模块获得到准确的感知结果后,才能让自动驾驶系统中的下游规控模块做出及时、正确的判断和行为决策。目前,具备自动驾驶功能的汽车中通常会配备包括环视相机传感器、激光雷达传感器以及毫米波雷达传感器在内的多种数据信息传感器来收集不同模态的信息,用于实现准确的感知任务。基于纯视觉的BEV感知算法因其较低的硬件成本和易于部署的特点,以及其输出结果能便捷地应用于各种下游任务,因此受到工业

使用C++实现机器学习算法:常见挑战及解决方案 使用C++实现机器学习算法:常见挑战及解决方案 Jun 03, 2024 pm 01:25 PM

C++中机器学习算法面临的常见挑战包括内存管理、多线程、性能优化和可维护性。解决方案包括使用智能指针、现代线程库、SIMD指令和第三方库,并遵循代码风格指南和使用自动化工具。实践案例展示了如何利用Eigen库实现线性回归算法,有效地管理内存和使用高性能矩阵操作。

探究C++sort函数的底层原理与算法选择 探究C++sort函数的底层原理与算法选择 Apr 02, 2024 pm 05:36 PM

C++sort函数底层采用归并排序,其复杂度为O(nlogn),并提供不同的排序算法选择,包括快速排序、堆排序和稳定排序。

人工智能可以预测犯罪吗?探索CrimeGPT的能力 人工智能可以预测犯罪吗?探索CrimeGPT的能力 Mar 22, 2024 pm 10:10 PM

人工智能(AI)与执法领域的融合为犯罪预防和侦查开辟了新的可能性。人工智能的预测能力被广泛应用于CrimeGPT(犯罪预测技术)等系统,用于预测犯罪活动。本文探讨了人工智能在犯罪预测领域的潜力、目前的应用情况、所面临的挑战以及相关技术可能带来的道德影响。人工智能和犯罪预测:基础知识CrimeGPT利用机器学习算法来分析大量数据集,识别可以预测犯罪可能发生的地点和时间的模式。这些数据集包括历史犯罪统计数据、人口统计信息、经济指标、天气模式等。通过识别人类分析师可能忽视的趋势,人工智能可以为执法机构

改进的检测算法:用于高分辨率光学遥感图像目标检测 改进的检测算法:用于高分辨率光学遥感图像目标检测 Jun 06, 2024 pm 12:33 PM

01前景概要目前,难以在检测效率和检测结果之间取得适当的平衡。我们就研究出了一种用于高分辨率光学遥感图像中目标检测的增强YOLOv5算法,利用多层特征金字塔、多检测头策略和混合注意力模块来提高光学遥感图像的目标检测网络的效果。根据SIMD数据集,新算法的mAP比YOLOv5好2.2%,比YOLOX好8.48%,在检测结果和速度之间实现了更好的平衡。02背景&动机随着远感技术的快速发展,高分辨率光学远感图像已被用于描述地球表面的许多物体,包括飞机、汽车、建筑物等。目标检测在远感图像的解释中

算法在 58 画像平台建设中的应用 算法在 58 画像平台建设中的应用 May 09, 2024 am 09:01 AM

一、58画像平台建设背景首先和大家分享下58画像平台的建设背景。1.传统的画像平台传统的思路已经不够,建设用户画像平台依赖数据仓库建模能力,整合多业务线数据,构建准确的用户画像;还需要数据挖掘,理解用户行为、兴趣和需求,提供算法侧的能力;最后,还需要具备数据平台能力,高效存储、查询和共享用户画像数据,提供画像服务。业务自建画像平台和中台类型画像平台主要区别在于,业务自建画像平台服务单条业务线,按需定制;中台平台服务多条业务线,建模复杂,提供更为通用的能力。2.58中台画像建设的背景58的用户画像

Java JPA 面试题精选:检验你的持久化框架掌握程度 Java JPA 面试题精选:检验你的持久化框架掌握程度 Feb 19, 2024 pm 09:12 PM

什么是JPA?它与JDBC有什么区别?JPA(JavaPersistenceapi)是一个用于对象关系映射(ORM)的标准接口,它允许Java开发者使用熟悉的Java对象来操作数据库,而无需编写直接针对数据库的sql查询。而JDBC(JavaDatabaseConnectivity)是Java用于连接数据库的标准API,它需要开发者使用SQL语句来操作数据库。JPA将JDBC封装起来,为对象-关系映射提供了更方便、更高级别的API,简化了数据访问操作。在JPA中,什么是实体(Entity)?实体

实时加SOTA一飞冲天!FastOcc:推理更快、部署友好Occ算法来啦! 实时加SOTA一飞冲天!FastOcc:推理更快、部署友好Occ算法来啦! Mar 14, 2024 pm 11:50 PM

写在前面&笔者的个人理解在自动驾驶系统当中,感知任务是整个自驾系统中至关重要的组成部分。感知任务的主要目标是使自动驾驶车辆能够理解和感知周围的环境元素,如行驶在路上的车辆、路旁的行人、行驶过程中遇到的障碍物、路上的交通标志等,从而帮助下游模块做出正确合理的决策和行为。在一辆具备自动驾驶功能的车辆中,通常会配备不同类型的信息采集传感器,如环视相机传感器、激光雷达传感器以及毫米波雷达传感器等等,从而确保自动驾驶车辆能够准确感知和理解周围环境要素,使自动驾驶车辆在自主行驶的过程中能够做出正确的决断。目

See all articles