// 21点游戏 分为人机对战和人人对战
// 玩家每次抽一张牌 牌的点数为1-10点随机数 谁更接近21点谁就获胜
let readline = require("readline-sync");
// 清屏函数
let clear = () => process.stdout.write(process.platform === 'win32' ? '\x1Bc' : '\x1B[2J\x1B[3J\x1B[H');
// 抽牌函数 接收一个参数 玩家对象
let takeCard = function (player) {
let point = Math.floor(Math.random() * 10 + 1); // 随机获取一个点数
console.log(`你抽取到的点数为:${point}`);
player.titlePoint += point; // 改变玩家对象的总点数
}
// 结果比较函数 接收2个参数 两个玩家对象
let judge = function (player1, player2) {
if (player1.titlePoint > player2.titlePoint) {
return 1;
}
else if (player1.titlePoint < player2.titlePoint) {
return 2;
}
else {
return 0;
}
}
// 主函数
let main = function () {
let useSys = true; // 是否使用系统 默认值true代表一直使用
while (useSys) {
clear();
console.log("欢迎来到21点的世界");
console.log("请选择游戏选项: 1.单人模式 2.双人模式 3.游戏说明 4.退出游戏");
let funcSelect = parseInt(readline.question(""));
switch (funcSelect) {
// 单人模式
case 1:
{
// 首先初始化两个对象,一个玩家,一个电脑
let player = { victory: 0, titlePoint: 0 };
let computer = { victory: 0, titlePoint: 0 };
let continuePlay = true; // 是否继续单人模式
while (continuePlay) {
let isTakeCard = true; // 玩家是否有资格抽取下一张牌 默认是true 有资格抽取
// 玩家抽牌的循环
while (isTakeCard) {
clear();
console.log(`当前的总点数为:${player.titlePoint}`);
console.log("是否要抽取一张牌?(Y/N)");
let isTake = readline.question("");
switch (isTake) {
case "Y":
case "y":
takeCard(player); // 用户已经抽取了一张牌,里面有点数了
// 玩家每抽取一张牌,都要进行是否超过21点的判断 如果超过21点,就不能继续抽牌了
// 直接将isTakeCard值改为false
if (player.titlePoint > 21) {
console.log("你已经爆炸了!");
readline.question("");
isTakeCard = false;
break;
}
console.log("\n按回车键继续");
readline.question("");
break;
case "N":
case "n":
isTakeCard = false;
break;
default:
console.log("输入有误,请重新输入");
readline.question("");
}
}
// 如果退出了上面的while,说明两种情况,一是玩家爆了,二是玩家主动退出来的
// 所以我们首先判断玩家的总点数是否大于21
if (player.titlePoint > 21) {
console.log("电脑获胜");
computer.victory++;
}
else {
// 如果没有进入上面的if,说明玩家是主动退出来的
// 那么我们就让电脑对象生成总点数,然后将两个对象传入judge函数进行比较
computer.titlePoint = Math.floor(Math.random() * 7 + 15); // 电脑随机的总点数为15-21的随机数
console.log(`你的总点数为${player.titlePoint},电脑的总点数为${computer.titlePoint}`);
let result = judge(player, computer);
// 根据judge函数返回的结果来显示不同的信息
switch (result) {
case 0:
console.log("本局为平局,不加分");
break;
case 1:
console.log("玩家获胜");
player.victory++;
break;
case 2:
console.log("电脑获胜");
computer.victory++;
break;
}
}
// 打印信息
console.log("\n当前比分如下:");
console.log(`玩家:${player.victory} vs 电脑:${computer.victory}`);
readline.question("");
// 询问玩家是否要继续单人模式 如果不继续了,直接将continuePlay修改为false
while (true) {
console.log("是否继续游戏?(Y/N)");
let isAgain = readline.question("");
// 如果要继续单人模式 那么需要将两个对象的总点数重置为0
if (isAgain === 'Y' || isAgain === 'y') {
player.titlePoint = 0;
computer.titlePoint = 0;
break;
}
else if (isAgain === 'N' || isAgain === 'n') {
continuePlay = false;
break;
}
else {
console.log("输入有误,请重新输入\n");
}
}
}
// 能够来到这里,说明玩家输入的n,这时continuePlay的值为false
// 打印最终结果即可
clear();
console.log("最终比分如下:");
console.log(`玩家:${player.victory} vs 电脑:${computer.victory}`);
console.log("\n按回车键返回");
readline.question("");
}
break;
// 双人模式
case 2:
{
// 和单人游戏模式一样,还是初始化两个对象,不过这两个对象多了一个isTakeCard属性
let player1 = { victory: 0, titlePoint: 0, isTakeCard: true };
let player2 = { victory: 0, titlePoint: 0, isTakeCard: true };
// continuePlay变量表示是否继续双人模式
let continuePlay = true;
while (continuePlay) {
// 根据两个玩家对象的isTakeCard属性值判断是否抽牌,只要两个对象有一个属性值为true就会进入while循环
while (player1.isTakeCard || player2.isTakeCard) {
// 根据玩家1的isTakeCard属性值来判断玩家1是否抽牌
if (player1.isTakeCard) {
let inputValidate = true; // 此变量为输入验证 用于后面验证玩家的输入
while (inputValidate) {
clear();
// 在抽牌之前首先打印当前的点数信息,然后开始询问玩家是否抽牌
console.log("总点数:")
console.log(`玩家A:${player1.titlePoint} vs 玩家B:${player2.titlePoint}`);
console.log("玩家A 是否抽牌?(Y/N)");
let isTake = readline.question("");
switch (isTake) {
case "Y":
case "y":
inputValidate = false; // 做输入验证
takeCard(player1); // 抽一张牌
readline.question("");
// 大于21,直接将两个玩家的isTakeCard都修改为false,这样可以退出上上个while
if (player1.titlePoint > 21) {
player1.isTakeCard = false;
player2.isTakeCard = false;
}
break;
case "N":
case "n":
// 代表玩家不抽牌了,将isTakeCard属性改为false
inputValidate = false;
player1.isTakeCard = false;
break;
default:
console.log("输入有误,请重新输入");
readline.question("");
}
}
}
// 和上面相同
if (player2.isTakeCard) {
let inputValidate = true;
while (inputValidate) {
clear();
console.log("总点数:")
console.log(`玩家A:${player1.titlePoint} vs 玩家B:${player2.titlePoint}`);
console.log("玩家B 是否抽牌?(Y/N)");
let isTake = readline.question("");
switch (isTake) {
case "Y":
case "y":
inputValidate = false;
takeCard(player2);
readline.question("");
if (player2.titlePoint > 21) {
player1.isTakeCard = false;
player2.isTakeCard = false;
}
break;
case "N":
case "n":
inputValidate = false;
player2.isTakeCard = false;
break;
default:
console.log("输入有误,请重新输入");
readline.question("");
}
}
}
}
// 代码来到这里说明两个玩家的isTakeCard都为false,接下来直接进行比较即可
if (player1.titlePoint > 21) {
console.log("玩家A已爆炸!");
console.log("玩家B获胜");
player2.victory++;
}
else if (player2.titlePoint > 21) {
console.log("玩家B已爆炸!");
console.log("玩家A获胜");
player1.victory++;
}
else {
let result = judge(player1, player2);
switch (result) {
case 0:
console.log("本局为平局,不加分");
break;
case 1:
console.log("玩家A获胜");
player1.victory++;
break;
case 2:
console.log("玩家B获胜");
player2.victory++;
break;
}
}
console.log("\n当前比分如下:");
console.log(`玩家A:${player1.victory} vs 玩家B:${player2.victory}`);
readline.question("");
while (true) {
console.log("是否继续游戏?(Y/N)");
let isAgain = readline.question("");
if (isAgain === 'Y' || isAgain === 'y') {
player1.titlePoint = 0;
player2.titlePoint = 0;
player1.isTakeCard = true;
player2.isTakeCard = true;
break;
}
else if (isAgain === 'N' || isAgain === 'n') {
continuePlay = false;
break;
}
else {
console.log("输入有误,请重新输入\n");
}
}
}
clear();
console.log("最终比分如下:");
console.log(`玩家A:${player1.victory} vs 玩家B:${player2.victory}`);
console.log("\n按回车键返回");
readline.question("");
}
break;
// 游戏说明
case 3:
{
clear();
console.log("单人模式规则:");
console.log("单人模式下玩家可以连续抽牌,每回合抽取的点数为1-10点中任意一个点数");
console.log("所有点数相加不能超过21点,然后总点数和电脑点数进行比较,谁更接近21点谁就算胜利\n");
console.log("双人模式规则:");
console.log("两名玩家轮流抽牌,在不超过21点的前提下进行总点数的比较,谁更接近21点谁就算胜利\n");
console.log("按回车键返回");
readline.question("");
}
break;
// 退出游戏
case 4:
{
// 要退出游戏 直接将useSys修改为false
useSys = false;
}
break;
}
}
clear();
console.log("Thank you for playing");
}
main();

JavaScript中纯JS写21点游戏的更多相关文章

  1. 纯JS写的2048游戏,分享之

    这几天玩儿着2048这个游戏,突然心血来潮想练习下敲代码的思路.于是乎就模仿做了一个,到眼下位置还没有实现动态移动,不是非常好看,只是玩儿着自己模仿的小游戏还是蛮爽的,哈哈 假设没有玩儿过这个游戏,最 ...

  2. javascript中外部js文件取得自身完整路径得办法

    原文:javascript中外部js文件取得自身完整路径得办法 有时候我们需要引入一个外部js文件,这个js文件又需要用到自己的路径或者是所在的目录,别问怎么又这么变态的需求,开发做久了各种奇葩需求也 ...

  3. 纯JS单页面赛车游戏代码分享

    分享一个以前写的小游戏,纯js游戏,代码很简单.欢迎大家来喷呦! 效果图: 代码展示://直接复制到html文件即可 支持IE9+版本 <!DOCTYPE html> <html&g ...

  4. 纯js写图片轮播插件

    最近终于写成了自己创作的图片轮播插件,使用原生js编写.与目前网上流行的轮播插件相比,功能和效果稍弱,但是使用起来相当方便. 先看html代码 <!DOCTYPE html> <ht ...

  5. 使用纯js写的一个分页

    上图晒效果: 网上确实有很多分页的插件以及开源代码,单本是一个后台开发猿,前台css等样式还驾驭不住,所以就开始自己去写了.其实这个分页原理很简单,就是用ajax往后台传值(当前页码),后台使用lim ...

  6. 用html5 canvas和JS写个数独游戏

    为啥要写这个游戏? 因为我儿子二年级数字下册最后一章讲到了数独.他想玩儿. 因为我也想玩有提示功能的数独. 因为我也正想决定要把HTML5和JS搞搞熟.熟悉一个编程平台,最好的办法,就是了解其原理与思 ...

  7. 纯JS写最简单的图片轮播

    非常简单的一个大图轮播,通过将控制显示位置来进行轮播效果,写来给正在学习的新手朋友们参考交流. 先看效果:(实际效果没有这么快) 先看布局: <div id="display" ...

  8. 纯JS写出日历

    封装代码: (function(cmf){ cmf.showDcalendar=function(){ var fnname=cmf.fn var id="cmfrili2" va ...

  9. 纯JS写动态分页样式效果

    效果图如下: html: <body> <div> <table id="btnbox"> <tbody> <tr>&l ...

随机推荐

  1. springboot java.util.NoSuchElementException: No value present 异常处理

    使用jpa查询的时候,如果查询不到数据,就会返回这个错误,下面是处理方法. @Override public User findByEmail(String email) { User user = ...

  2. R语言 判断

    R语言判断 决策结构要求程序员指定要由程序评估或测试的一个或多个条件,以及如果条件被确定为真则要执行的一个或多个语句,如果条件为假则执行其他语句. 以下是在大多数编程语言中的典型决策结构的一般形式 R ...

  3. 【锁】Innodb锁

    InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...

  4. Intervals POJ - 3680

    传送门 给定数轴上n个带权区间$[l_i,r_i]$,权值为$w_i$ 选出一些区间使权值和最大,且每个点被覆盖次数不超过k次. 离散+拆点,最大费用可行流(跑到费用为负为止) 第一部分点按下标串起来 ...

  5. NX二次开发-UFUN修改当前导出CGM文件选项设置UF_CGM_set_session_export_options

    文章转载自唐康林NX二次开发论坛,原文出处: http://www.nxopen.cn/thread-126-1-1.html 刚才有同学问到这个问题,如果是用NXOpen来做,直接录制一下就可以了: ...

  6. ueditor使用心得

    UEditor使用手册 配置jdk 1.6+ Apache Tomcat6.0+ Ueditor官网下载 部署 安装好jdk和apache后,我们开始部署代码 我们在apache的安装目录下,找到we ...

  7. C++输入cin详解

    输入原理: 程序的输入都建有一个缓冲区,即输入缓冲区.一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据.正因为cin函数是直接从缓冲区取数据 ...

  8. Windows内核驱动开发入门学习资料

    声明:本文所描述的所有资料和源码均搜集自互联网,版权归原始作者所有,所以在引用资料时我尽量注明原始作者和出处:本文所搜集资料也仅供同学们学习之用,由于用作其他用途引起的责任纠纷,本人不负任何责任.(本 ...

  9. 制作windows puppet openstack镜像

    由于电信需要远程部署软件,拟使用puppet进行远程服务管理 前提 windows系统已经安装 windows已经安装virtio driver 远程桌面开启,最好关闭防火墙 设置MTU 在没有安装c ...

  10. LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)

    题目标签:Linked List, Stack 题目给了我们一个 Linked List,让我们找出对于每一个数字,它的下一个更大的数字. 首先把 Linked List 里的数字 存入 ArrayL ...