在控制台中实现“单词竞猜”游戏 C# 猜词游戏
场景
设计规则
a) 这是一个单人玩的游戏。
b) 可以分三个级别,分别是高级、中级、低级。不同级别对应的单词系列也不一样。要求一旦玩家选定了要玩的级别,应当先提示它关于此级别最高分是多少,是谁创下的记录,然后再开始游戏。
c) 游戏开始后,应显示如下信息:
i. 剩余可用竞猜次数(竞猜次数的初始值等于被猜的单词遗漏的字符数加5),
ii. 玩家所得分数:完全猜对一个单词得一分。
iii. 已用时间:要每10秒更新一次已用时间的显示。
iv. 竞猜的单词。只显示每个单词的部分字母,并且这些字母是随机显示出来的。刻意遗漏的字母应当使用*替代。应当有多少字母被显示出来,视单词的长度而定,如果单词本身较长,则多显示,反之亦然。
d) 游戏结束前,比较一家玩家的成绩与文件中存储的词汇通英雄的成绩,如果前者成绩更高,需要将如下信息保存在文件中。(成绩:猜对的单词数*100/一共花费的时间)
i. 玩家姓名
ii. 所用时间
iii. 分数。
另外,要注意的是,如果发现他们分数相同就比较使用的时间。
还有,不同级别的词汇通英雄信息应当分别放在不同的文件中。
e) 如果玩家在给定次数内(选取20次)没有猜出5个单词,则游戏结束。
l 实验方法
参照学生信息管理系统。
1.
创建一个线程专门负责时间提醒
2.
采用两种用户,管理员负责将游戏初始化,更新词汇表,之前自动更新和逐个输入
3.
玩家玩游戏
| 单词竞猜 | |
|---|---|
| Program类 | 主函数 |
| TextOperateClass类 | 文本操作类 |
玩家主函数:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Timers;
using System.Threading; namespace WordsPlay
{
class Program
{
static DateTime initTime;
static void Main(string[] args)
{
Console.WriteLine("------------------------------------------------");
Console.WriteLine("------------ ------------");
Console.WriteLine("------------ 欢迎来到单词竞猜游戏 ------------");
Console.WriteLine("------------ CopyRight:Sunsea ------------");
Console.WriteLine("------------ ------------");
Console.WriteLine("------------------------------------------------"); Console.WriteLine("请输入你的姓名:");
string username = string.Format(Console.ReadLine()); //玩家姓名
Console.WriteLine("请选择游戏级别:\n\t1.高级 \n\t2.中级 \n\t3.低级"); int grade = int.Parse(Console.ReadLine()); //玩家选择的等级 while (grade < 1 || grade > 3)
{
Console.WriteLine("请输入1~3的正整数!");
grade = int.Parse(Console.ReadLine());
} //查询最高分
string s = TextOperateClass.ReadMaxScore(grade);
int maxScore = Convert.ToInt16(s.Substring(s.IndexOf("#") + 1, s.LastIndexOf("#") - s.IndexOf("#")-1));
string maxScoreUsername = s.Substring(s.LastIndexOf("#") + 1, s.Length - s.LastIndexOf("#") - 1); //输出记录信息
string maxScoreMessage = string.Format("当前最高分记录{0}分,记录保持者{1}",maxScore,maxScoreUsername);
Console.WriteLine(maxScoreMessage); //初始化玩家分数,没猜对一个得一分
int playerScore = 0;
//猜词次数
int guessRightNums = 0; //可以无限制猜词,最大循环次数1000
int countWhile = 1000;
//如果在20次内没能猜正5个,退出 initTime = DateTime.Now; //记录猜词起始时间 //单独线程用于定时
Thread timeThread = new Thread(TimeRemind);
timeThread.Start(); //在主线程调用TimeRemind方法 while (countWhile>0)
{ string fullWord = TextOperateClass.ReadFullWords(grade); //获取一个完整单词
string vagueWord = TextOperateClass.VagueWords(fullWord); //获取一个被*替换字母的单词
Console.WriteLine("请猜{0}的完整拼写:",vagueWord); //一个单词有6次参测机会
int SingleWordGuessNums = 6;
while (SingleWordGuessNums>0)
{
string playerGuessWord = Console.ReadLine(); //获取玩家猜测
if (playerGuessWord.Equals(fullWord))
{
guessRightNums++;
break;
}
else
{
Console.WriteLine("你的猜测有误,是否放弃本单词猜测:放弃<y>,不放弃继续猜!");
try
{
//如果输入字符超过一个,抛出异常
if (char.Parse(Console.ReadLine()) == 'y')
break;
}
catch (Exception)
{ Console.WriteLine("输入错误");
}
} SingleWordGuessNums--;
} //判断是继续还是退出
string isContinue;
while (true)
{
Console.WriteLine("继续请输<y>,退出请输<n>?");
isContinue = Console.ReadLine();
if (isContinue != "y" && isContinue != "n" && isContinue != "Y" && isContinue != "N")
Console.WriteLine("请按提示正确输入,是否继续!");
else
break;
}
if (isContinue == "n")
break; //猜词次数自减
countWhile--;
//如果在20次中没猜正5个,游戏强退
if (countWhile <= 1000 - 20 && guessRightNums < 5)
{
Console.WriteLine("Sorry,你在20个单词中猜正确的单词不达5个,游戏结束");
break;
} } //获取用时
DateTime endTime = DateTime.Now;
TimeSpan userTime = endTime - initTime;
double userTimeSeconds = userTime.TotalSeconds; #region
//更新最高分
if (guessRightNums > maxScore)
{
TextOperateClass.UpdataMaxScore(grade, guessRightNums, username);
Console.WriteLine("恭喜你打破了得分记录");
}
string messageMaxScore = string.Format("你<{0}>在{1}中的得分是{2}", username, TextOperateClass.GradeString(grade),guessRightNums);
Console.WriteLine(messageMaxScore);
#endregion //词汇通英雄操作区域
#region
//查询词汇通英雄成绩
string wordsHero =TextOperateClass.ReadMaxPerformance(grade);
int maxPerformance = Convert.ToInt16(wordsHero.Substring(wordsHero.IndexOf("#", 3) + 1, wordsHero.LastIndexOf("#") - wordsHero.IndexOf("#", 3) - 1));
int totalTime =Convert.ToInt16( wordsHero.Substring(wordsHero.LastIndexOf("#") + 1, wordsHero.Length - wordsHero.LastIndexOf("#") - 1)); //成绩=猜对的单词数*100/一共花费的时间;
playerScore = guessRightNums * 100 / (int)userTimeSeconds; //更新成绩
if (playerScore > maxPerformance || (playerScore == maxPerformance && (int)userTimeSeconds < totalTime))
{
messageMaxScore = string.Format("恭喜你<{0}>成为{1}中新的词汇通英雄,你的成绩{2},用时{3}秒", username, TextOperateClass.GradeString(grade), playerScore, (int)userTimeSeconds);
Console.WriteLine(messageMaxScore);
TextOperateClass.UpdataMaxperformance(grade, username, playerScore, (int)userTimeSeconds);
}
#endregion
timeThread.Abort();
Console.WriteLine("------------------------------------------------");
Console.WriteLine("------------ ------------");
Console.WriteLine("----------- 欢迎再来,按任意键结束 -----------");
Console.WriteLine("------------ CopyRight:Sunsea ------------");
Console.WriteLine("------------ ------------");
Console.Write("------------------------------------------------");
Console.ReadLine();
}
//定时提醒 10s
public static void TimeRemind()
{
System.Timers.Timer t = new System.Timers.Timer();
t.Elapsed += new ElapsedEventHandler(writesecond);
t.Interval = 10000;
t.Enabled = true;
Console.ReadLine();
}
public static void writesecond(object source, ElapsedEventArgs e)
{
TimeSpan userTime = DateTime.Now - initTime;
Console.WriteLine(string.Format("已用时{0}秒",(int)userTime.TotalSeconds));
}
}
}
文本操作类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System.Timers; namespace WordsPlay
{
public class TextOperateClass
{
//获取级别
public static string GradeString(int grade)
{
string gradeString = null;
switch (grade)
{
case 1:
gradeString = "高级";
break;
case 2:
gradeString = "中级";
break;
case 3:
gradeString = "初级";
break;
}
return gradeString;
} //根据级别获取单词存储路径
private static string GradePath(int grade)
{
string gradePath = null;
switch (grade)
{
case 1:
gradePath =@"e:\01111139\HighLevelWord.txt";
break;
case 2:
gradePath = @"e:\01111139\MiddleLevelWord.txt";
break;
case 3:
gradePath = @"e:\01111139\LowLevelWord.txt";
break;
}
return gradePath;
} //按级别读取最高分
public static string ReadMaxScore(int grade)
{
//获取级别
string gradeString = GradeString(grade); FileStream fs = new FileStream(@"e:\01111139\MaxScore.txt",FileMode.Open,FileAccess.Read);
StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default); string line = null;
while ((line = sr.ReadLine()) != null)
{
int count = line.IndexOf(gradeString);
if (count == 0)
{
sr.Close();
fs.Close();
return line;
}
} //暂时没有记录
sr.Close();
fs.Close();
return null; } //读取最高成绩
public static string ReadMaxPerformance(int grade)
{
//获取级别
string gradeString = GradeString(grade); FileStream fs = new FileStream(@"e:\01111139\WordsHero.txt", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default); string line = null;
while ((line = sr.ReadLine()) != null)
{
int count = line.IndexOf(gradeString);
if (count == 0)
{
sr.Close();
fs.Close();
return line;
}
} //暂时没有记录
sr.Close();
fs.Close();
return null; }
//更新得分 //grade及为对应的行数
public static void UpdataMaxScore(int grade, int score, string username)
{
//获取级别
string gradeString = GradeString(grade); string newLineValue = string.Format("{0}#{1}#{2}", gradeString, score, username);//要更新的行 FileStream fs = new FileStream(@"e:\01111139\MaxScore.txt", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default); //定义一个数组存放内容
string[] maxScoreLine = new string[3];
string line;
for (int i = 0; (line = sr.ReadLine()) != null; i++)
{
maxScoreLine[i] = line;
}
sr.Close();
fs.Close(); //清空文档内容 FileStream fsw = new FileStream(@"e:\01111139\MaxScore.txt", FileMode.Create, FileAccess.Write); //覆盖创建
StreamWriter sw = new StreamWriter(fsw, System.Text.Encoding.Default); string subLine;
foreach (string str in maxScoreLine)
{
subLine = str.Substring(0, 2);
if (subLine.Equals(gradeString))
{
sw.WriteLine(newLineValue);
}
else
{
sw.WriteLine(str);
}
}
sw.Close();
fsw.Close();
} //更新成绩
public static void UpdataMaxperformance(int grade, string username, int playerScore, double userTimeSeconds)
{
//获取级别
string gradeString = GradeString(grade); string newLineValue = string.Format("{0}#{1}#{2}#{3}", gradeString, username, playerScore, userTimeSeconds);//要更新的行 FileStream fs = new FileStream(@"e:\01111139\WordsHero.txt", FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default); //定义一个数组存放内容
string[] maxScoreLine = new string[3];
string line;
for (int i = 0; (line = sr.ReadLine()) != null; i++)
{
maxScoreLine[i] = line;
}
sr.Close();
fs.Close(); //清空文档内容 FileStream fsw = new FileStream(@"e:\01111139\WordsHero.txt", FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(fsw, System.Text.Encoding.Default); string subLine;
foreach (string str in maxScoreLine)
{
subLine = str.Substring(0, 2);
if (subLine.Equals(gradeString))
{
sw.WriteLine(newLineValue);
}
else
{
sw.WriteLine(str);
}
}
sw.Close();
fsw.Close();
} //读取单词,
//根据读取到的单词,将单词模糊化
public static string VagueWords(string fullWord)
{ //模糊化处理
//将单词转化成字符数组
char[] arrWord = fullWord.ToCharArray(); //*代替字符数是单词长度的1/3
int nums = arrWord.Length / 3; List<int> myListRdm = new List<int>();
myListRdm = CreateNum(nums,0,arrWord.Length); //将随机数对应的位置,字母特换成*
int index=0;
for (int i = 0; i < myListRdm.Count; i++)
{
index=myListRdm[i];
arrWord[index] = '*';
} //将arrWord[]数组中的元素生成字符串
StringBuilder st = new StringBuilder();
foreach (char c in arrWord)
{
st = st.Append(c);
}
string vagueWord = st.ToString(); return vagueWord; //可以根据单词长度获得遗漏的字符数 } //在【min,max】区间中产生num个不相等的随机数,存在数组中,返回
private static List<int> CreateNum(int nums,int min,int max)
{
List<int> MyList = new List<int>();
Random random = new Random(); //循环的次数为产生随机数个数
while (true)
{
int i = random.Next(min, max);
if (!MyList.Contains(i))
{
if (MyList.Count < nums)
{
MyList.Add(i);
}
else
break;
}
}
return MyList; } //返回完整单词
//自行产生随机数读取。随机数的范围是(0,单词总数)
public static string ReadFullWords(int grade)
{
//获取单词获取路径
string gradePath = GradePath(grade); FileStream fs = new FileStream(gradePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default);
string wordsString = sr.ReadToEnd(); //Regex是正则表达式啊的类啊,引用using System.Text.RegularExpressions就可以看到了
string[] wordsArr = Regex.Split(wordsString, " "); Random rd = new Random(); int num = rd.Next(1, wordsArr.Length); return wordsArr[num];
} }
}
说明事项
1、文本操作乱码问题,运行之前需要在E盘创建01111139文件夹,E:\01111139\*.txt
2、更新文本文档中的内容可以通过将文本文档读取放在数组中,然后覆盖创建文档,
更新数组,然后在写回。
3、这里面用了委托机制,创建一个单独的线程负责时间提醒,个人认为:基于控制台时间提醒不适宜,会导致界面很乱,读者可以考虑删除。
4、就问题实现要求而言,最高分和词汇通英雄有点重复,做一个即可。
这样玩家游戏就能用了,管理员端可以参考下一篇博客《单词竞猜游戏之管理员端》
在控制台中实现“单词竞猜”游戏 C# 猜词游戏的更多相关文章
- 【原创Android游戏】--猜数字游戏V1.1 --数据存储,Intent,SimpleAdapter的学习与应用
--------------------------------------------------------------- V0.1版本 上次做完第一个版本后,发现还有一些漏洞,并且还有一些可以添 ...
- 【原创Android游戏】--猜数字游戏Version 0.1
想当年高中时经常和小伙伴在纸上或者黑板上或者学习机上玩猜数字的游戏,在当年那个手机等娱乐设备在我们那还不是很普遍的时候是很好的一个消遣的游戏,去年的时候便写了一个Android版的猜数字游戏,只是当时 ...
- Java 7.35 游戏:猜字游戏(C++&Java)
Ps: 有人可能好奇我为什么大费周章的去写主函数,而不直接把所有操作放在类中,Why?类就好比骨干(存放核心的数据和功能),最好提供接口, 避免了类中的输入输出,当然,这也不是绝对的. C++: #i ...
- JSP简单练习-猜字母游戏
<!-- guessCharExample.jsp --> <%@ page contentType="text/html; charset=gb2312" %& ...
- C# 计算字符串在控制台中的显示长度
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- 利用跨域请求来隐藏firbug控制台中的Ajax请求
本文链接:http://www.orlion.ml/63/ 普通jquery的Ajax请求在控制台中是可见的,如下: 而在利用jsonp(json with padding)进行Ajax跨域时,发现A ...
- 在 C# 控制台中记录异常日志并输出
最近做了一个小程序,要求在控制台中记录程序运行的异常并输出到指定的文件夹中,以下是我的具体的程序代码: public static void ErrorLog(Exception ex) { stri ...
- 关于 JavaScript 中一个小细节问题 (在控制台中直接 {Name:'王尼玛',Age:20} 对象报错问题)
在 Chrome 浏览器,大家可能遇到这样一个小问题. 随便输入一个 Object 对象 ,比如 {Name:'王尼玛',Age:20} ,将会报错.之前,也从来没去考虑过到底是为啥原因. 今天,刚 ...
- 转:在控制台中调试AngularJS应用
在控制台中调试AngularJS应用 在创建AngularJS应用时,一个很棘手的问题是如何在Chrome,Firefox,以及IE的JavaScript控制台中访问深藏在应用中的数据和服务.本文将会 ...
随机推荐
- LeetCode532. K-diff Pairs in an Array
Description Given an array of integers and an integer k, you need to find the number of unique k-dif ...
- Linux中解压缩命令gzip和unzip的一点说明
inux中解压缩命令gzip和unzip的一点说明 转载 2014年10月29日 20:37:35 20741 Linux 常用的压缩命令有 gzip 和 zip,两种压缩包的结尾不同:zip 压 ...
- 四个 jQuery 方法:
append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插入内容 before() - 在被选元素之前插入内容
- HDU 3080 The plan of city rebuild(除点最小生成树)
题意 一个城市原来有l个村庄 e1条道路 又添加了n个村庄 e2条道路 后来后销毁了m个村庄 与m相连的道路也销毁了 求使全部未销毁村庄相互连通最小花费 不能连通输出what a pity ...
- oracle em手动配置
转载自:http://www.cnblogs.com/sopost/archive/2010/08/14/2190098.html 用emca配置em emca是一个命令提示符,使用格式和方法在命令提 ...
- NetCore 中 EFcore的DbFirst和CodeFirst混合 使用注意
NetCore 最近很火热.笔者想把自己以前的旧项目迁移到NetCore平台. 先用EFcore的DBFirst根据数据库创建实体类,然后加入数据库版本控制功能也就是EFcore的CodeFirst部 ...
- PHP制作姓名、学号。爱好等窗口
if (radioButton1.Checked == true) textBox2.Text = 姓名: + textBox1.Text + 性别: + radi ...
- Android开发:《Gradle Recipes for Android》阅读笔记(翻译)3.2——设置Flavors和Variants
问题: 需要构建大体上一样,但是使用不同资源或者类的应用. 解决方案: 产品的flavors可以帮助你对同一个app创建不同的版本. 讨论: build types是开发过程的一部分,一般用来将app ...
- 在Windows 7 (SP1)上安装Visual Studio 2015
背景说明:最近重装了Windows 7 系统,那就顺手装个Visual Studio 2015吧,没想到一案装就报错(具体没截图了).只有Windows8 或是Windows 10才能装 2015?答 ...
- 整合swagger2生成Restful Api接口文档
整合swagger2生成Restful Api接口文档 swagger Restful文档生成工具 2017-9-30 官方地址:https://swagger.io/docs/specificati ...