在控制台中实现“单词竞猜”游戏 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、就问题实现要求而言,最高分和词汇通英雄有点重复,做一个即可。
这样玩家游戏就能用了,管理员端可以参考下一篇博客《单词竞猜游戏之管理员端》