【人机交互实验】命令行数独游戏 C#
程序员文章站
2022-06-04 16:12:26
...
题目
a) 设计一个命令行界面的游戏,登入游戏界面后,应该有游戏规则说明,按键说明。
b) 进入游戏前应该有难度选择:1表示简单、2表示中等、3表示困难。
c) 在游戏主界面中有可以循环输入数独值、可以连续玩好几局直到退出、检查结果、查看答案、新开一局的功能。
d) 信息提示功能:输入错误时应有提示、游戏失败或获取胜利时应有庆祝界面等。
展示
源码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jiaohu1
{
class Sdnum
{
public int num;
public ConsoleColor c;
public Sdnum(int x = 0, ConsoleColor col = ConsoleColor.White)
{
num = x;
c = col;
}
public void ChangeColor(ConsoleColor col)
{
c = col;
}
public void ChangeNum(int n)
{
num = n;
}
public void Display()
{
if (c != ConsoleColor.White)
Console.ForegroundColor = c;
Console.Write(" ");
if (num >= 1 && num <= 9)
Console.Write(num);
else if (num == 0)
Console.Write(" ");
else if (num == 10)
Console.Write("x");
if (c != ConsoleColor.White)
Console.ForegroundColor = ConsoleColor.White;
Console.Write(" ");
}
}
class Line
{
string s;
public Line(string line)
{
s = line;
}
public void Display(ConsoleColor col)
{
Console.ForegroundColor = col;
Console.Write(s);
Console.ForegroundColor = ConsoleColor.White;
}
public void Display2()
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(s.Substring(0, 1));
Console.ForegroundColor = ConsoleColor.White;
Console.Write(s.Substring(1, 11));
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(s.Substring(12, 1));
Console.ForegroundColor = ConsoleColor.White;
Console.Write(s.Substring(13, 11));
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(s.Substring(24, 1));
Console.ForegroundColor = ConsoleColor.White;
Console.Write(s.Substring(25, 11));
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(s.Substring(36, 1));
Console.ForegroundColor = ConsoleColor.White;
}
}
class Menu
{
int choose, type, top_ch;
List<string> c = new List<string>();
string top;
string left, right;
string blank;
string bottom;
public Menu(int menuType)
{
type = menuType;
}
public void Init1()
{
choose = 0;
c.Add("a--进入数独游戏");
c.Add("b--游戏规则说明");
c.Add("c--按键说明");
c.Add("e--退出游戏");
top = "********欢迎进入数独游戏********";
top_ch = 8;
left = "<< ";
right = ">>";
blank = "<< >>";
bottom = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
}
public void Init2()
{
choose = -1;
c.Add("数独游戏在9×9的方格内进行,分为3×3的小方格,被称为区.");
c.Add("数独游戏首先从已经填入数字的格子开始.");
c.Add("用1至9之间的数字填满空格,一个格子只能填入一个数字.");
c.Add("每个数字在每一行只能出现一次;");
c.Add("每个数字在每一列只能出现一次;");
c.Add("每个数字在每一区只能出现一次;");
c.Add("总结这些规则,即每个数字在每一行,每一列和每一区只能出现一次.");
top = "*****************************数独游戏规则******************************";
top_ch = 6;
left = "<< ";
right = ">>";
blank = "<< >>";
bottom = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
}
public void Init3()
{
choose = -1;
c.Add("进入游戏后要输入3个数:所在行、所在列、其值.");
c.Add(" 3个数分别用空格隔开.");
c.Add(" 输完后用回车键进行确定.");
top = "*************************数独游戏按键说明*************************";
top_ch = 8;
left = "<< ";
right = ">>";
blank = "<< >>";
bottom = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
}
public void Init4()
{
choose = 0;
c.Add("a--简单");
c.Add("b--中等");
c.Add("c--困难");
c.Add("e--返回");
top = "************游戏难度选择************";
top_ch = 6;
left = "<< ";
right = ">>";
blank = "<< >>";
bottom = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
}
public void Init5()
{
choose = -1;
c.Add(" 恭喜!");
c.Add(" 你答对了");
c.Add(" 你真是个天才");
top = "**************庆祝**************";
top_ch = 2;
left = "<< ";
right = ">>";
blank = "<< >>";
bottom = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
}
public void Display()
{
Console.Clear();
int cleft = Math.Min(Math.Max((Console.WindowWidth - top.Length) / 2, 0), Console.WindowWidth - 1);
int ctop = Math.Min(Math.Max((Console.WindowHeight - c.Count - 7) / 2, 0), Console.WindowWidth - 1);
Console.SetCursorPosition(cleft, ctop++);
Console.WriteLine(top);
Console.SetCursorPosition(cleft, ctop++);
Console.WriteLine(blank);
Console.SetCursorPosition(cleft, ctop++);
Console.WriteLine(blank);
for (int i = 0; i < c.Count; i++)
{
Console.SetCursorPosition(cleft, ctop++);
Console.Write(left);
if (choose == i)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write(c[i]);
Console.ForegroundColor = ConsoleColor.White;
}
else
{
Console.Write(c[i]);
}
Console.SetCursorPosition(Math.Min(Math.Max(cleft + top.Length - 2 + top_ch, 0), Console.WindowWidth - 1), ctop - 1);
Console.WriteLine(right);
}
Console.SetCursorPosition(cleft, ctop++);
Console.WriteLine(blank);
Console.SetCursorPosition(cleft, ctop++);
Console.WriteLine(blank);
Console.SetCursorPosition(cleft, ctop++);
Console.WriteLine(bottom);
Console.SetCursorPosition(Math.Min(Math.Max((Console.WindowWidth - 10) / 2, 0), Console.WindowWidth - 1), ctop++);
Console.WriteLine("按Enter键继续...");
}
void Up()
{
choose -= 1;
if (choose == -1)
choose = c.Count - 1;
}
void Down()
{
choose += 1;
if (choose == c.Count)
choose = 0;
}
public int Listen()
{
ConsoleKeyInfo cki;
do
{
cki = Console.ReadKey();
if (type == 1)
{
switch (cki.Key.ToString())
{
case "UpArrow":
Up();
break;
case "DownArrow":
Down();
break;
case "A":
choose = 0;
break;
case "B":
choose = 1;
break;
case "C":
choose = 2;
break;
case "E":
choose = 3;
break;
}
Display();
}
} while (cki.Key != ConsoleKey.Enter);
return choose;
}
}
class Sudoku
{
List<Sdnum> map = new List<Sdnum>();
Line headLine = new Line("┏━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┳━━━┓");
Line normalLine = new Line("┣━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━╋━━━┫");
Line bottomLine = new Line("┗━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┻━━━┛");
int[] solution = new int[81]
{
2,1,6,4,8,9,7,5,3,
4,3,8,5,6,7,2,1,9,
7,9,5,1,3,2,8,6,4,
1,8,9,3,7,5,4,2,6,
3,2,4,6,1,8,9,7,5,
6,5,7,2,9,4,3,8,1,
8,6,2,9,4,1,5,3,7,
9,7,3,8,5,6,1,4,2,
5,4,1,7,2,3,6,9,8
};
int[] save = new int[81];
int choose,diff,left,top;
public void Init(int difficulty)
{
choose = -1;
diff = difficulty;
map.Clear();
for (int i = 0; i < 81; i++)
{
map.Add(new Sdnum());
save[i] = 0;
}
Random ran = new Random();
List<int> temp = new List<int>();
int k;
for (int i = 0; i < 81; i++)
temp.Add(i);
for (int i = 0; i < difficulty; i++)
{
k = ran.Next(0, temp.Count);
save[temp[k]] = 1;
map[temp[k]].ChangeNum(solution[temp[k]]);
temp.RemoveAt(k);
}
for (int i = 0; i < 81; i++)
{
if (save[i] != 1)
{
map[i].ChangeColor(ConsoleColor.Green);
}
}
}
void DisplayNumLine(int line)
{
int start = line * 9;
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write("┃");
Console.ForegroundColor = ConsoleColor.White;
for (int i = 0; i < 9; i++)
{
map[start + i].Display();
if (i == 2 || i == 5 || i == 8)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write("┃");
Console.ForegroundColor = ConsoleColor.White;
}
else
Console.Write("┃");
}
}
public void DisplayMenu()
{
Console.Clear();
List<string> c = new List<string>();
int top = 6;
c.Add("a--输入指定位置");
c.Add("b--检查结果");
c.Add("c--查看答案");
c.Add("d--再来一局");
c.Add("e--返回");
for (int i = 0; i < c.Count; i++)
{
Console.SetCursorPosition(5, top);
top += 2;
if (choose == i)
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write(c[i]);
if (choose == i)
Console.ForegroundColor = ConsoleColor.White;
}
}
public void Display()
{
left = (Console.WindowWidth - 40) / 2;
top = 0;
Console.SetCursorPosition(left + 2, top++);
Console.WriteLine("1 2 3 4 5 6 7 8 9");
Console.SetCursorPosition(left, top++);
headLine.Display(ConsoleColor.Blue);
for (int i = 0; i < 8; i++)
{
Console.SetCursorPosition(left - 1, top++);
Console.Write(i + 1);
DisplayNumLine(i);
Console.SetCursorPosition(left, top++);
if ((i + 1) % 3 == 0)
normalLine.Display(ConsoleColor.Blue);
else
normalLine.Display2();
}
Console.SetCursorPosition(left - 1, top++);
Console.Write(9);
DisplayNumLine(8);
Console.SetCursorPosition(left, top++);
bottomLine.Display(ConsoleColor.Blue);
Console.WriteLine();
}
void DisplaySolution()
{
Sudoku temp = new Sudoku();
temp.Init(81);
Console.Clear();
temp.Display();
Console.SetCursorPosition(left, top++);
Console.Write("按任意键继续...");
Console.ReadKey();
}
void CheckOut()
{
bool isOK=true;
DisplayMenu();
Display();
for(int i = 0; i < 81; i++)
{
if (map[i].num < 1 || map[i].num > 9 || (save[i] == 0 && map[i].c == ConsoleColor.Red))
{
isOK = false;
Console.SetCursorPosition(left, top++);
Console.Write("对不起,你的答案不正确,请再检查一下!");
Console.SetCursorPosition(left, top++);
Console.Write("按Enter键继续...");
break;
}
}
if (isOK)
{
Console.Clear();
Menu cele=new Menu(2);
cele.Init5();
cele.Display();
}
ConsoleKeyInfo cki;
do
{
cki = Console.ReadKey();
} while (cki.Key != ConsoleKey.Enter);
}
bool isRepeat(int i,int j,int k)
{
for (int m = 0; m < 9; m++)
if (map[m * 9 + j].num == k && m != i)
return true;
for (int n = 0; n < 9; n++)
if (map[i * 9 + n].num == k && n != j)
return true;
for (int p = (i / 3) * 3; p < (i / 3) * 3 + 3; p++)
for (int q = (j / 3) * 3; q < (j / 3) * 3 + 3; q++)
if (map[p * 9 + q].num == k && p != i && q != j)
return true;
return false;
}
void InputNum()
{
int i, j, k;
char temp;
DisplayMenu();
Display();
Console.SetCursorPosition(left, top++);
Console.Write("选择行号:");
temp = Console.ReadKey().KeyChar;
if (temp >= '1' && temp <= '9')
i = temp-'0';
else
{
Console.SetCursorPosition(left, top++);
Console.Write("非法的行号,应该输入1~9的数字");
Console.SetCursorPosition(left, top++);
Console.Write("请按任意键继续...");
Console.ReadKey();
InputNum();
return;
}
Console.Write(" 列号:");
temp = Console.ReadKey().KeyChar;
if (temp >= '1' && temp <= '9')
j = temp - '0';
else
{
Console.SetCursorPosition(left, top++);
Console.Write("非法的列号,应该输入1~9的数字");
Console.SetCursorPosition(left, top++);
Console.Write("请按任意键继续...");
Console.ReadKey();
InputNum();
return;
}
int n = (i - 1) * 9 + j-1;
if (save[n] == 1)
{
Console.SetCursorPosition(left, top++);
Console.Write("对不起,原题中该位置已经指定为"+map[n].num+",你不能修改这个值");
Console.SetCursorPosition(left, top++);
Console.Write("请按任意键继续...");
Console.ReadKey();
InputNum();
return;
}
Console.Write(" 填入的值:");
temp = Console.ReadKey().KeyChar;
if (temp >= '1' && temp <= '9')
k = temp - '0';
else
{
Console.SetCursorPosition(left, top++);
Console.Write("非法的值,应该输入1~9的数字");
Console.SetCursorPosition(left, top++);
Console.Write("请按任意键继续...");
Console.ReadKey();
InputNum();
return;
}
choose = -1;
map[n].ChangeNum(k);
if (isRepeat(i-1,j-1,k))
{
map[n].ChangeColor(ConsoleColor.Red);
}
else
map[n].ChangeColor(ConsoleColor.Green);
DisplayMenu();
Display();
Console.SetCursorPosition(left, top++);
Console.Write("填入成功");
Console.SetCursorPosition(left, top++);
Console.Write("请按任意键继续...");
for(int x = 0; x < 81; x++)
{
if (save[x] == 0)
if (isRepeat(x / 9, x % 9, map[x].num))
map[x].ChangeColor(ConsoleColor.Red);
else map[x].ChangeColor(ConsoleColor.Green);
}
Console.ReadKey();
DisplayMenu();
Display();
}
void QuickMode()
{
}
public int Listen()
{
ConsoleKeyInfo cki;
do
{
cki = Console.ReadKey();
switch (cki.Key.ToString())
{
case "A":
choose = 0;
InputNum();
break;
case "B":
choose = 1;
CheckOut();
choose = -1;
DisplayMenu();
Display();
break;
case "C":
choose = 2;
DisplaySolution();
choose = -1;
DisplayMenu();
Display();
break;
case "D":
choose = 3;
Init(diff);
DisplayMenu();
Display();
break;
case "E":
choose = 5;
return -1;
default:
DisplayMenu();
Display();
break;
}
} while (true);
}
}
class Program
{
static void Main(string[] args)
{
Sudoku sudoku = new Sudoku();
Menu startMenu = new Menu(1);
Menu rule = new Menu(2);
Menu Instr = new Menu(2);
Menu difficulty = new Menu(1);
startMenu.Init1();
rule.Init2();
Instr.Init3();
difficulty.Init4();
startMenu.Display();
int choose;
choose = startMenu.Listen();
do
{
switch (choose)
{
case 0:
difficulty.Display();
choose = difficulty.Listen() + 4;
break;
case 1:
rule.Display();
choose = rule.Listen();
break;
case 2:
Instr.Display();
choose = Instr.Listen();
break;
case 3:
return;
case -1:
case 7:
startMenu.Display();
choose = startMenu.Listen();
break;
case 4:
case 5:
case 6:
sudoku.Init(81 - ((choose - 3) * 20));
sudoku.DisplayMenu();
sudoku.Display();
choose = sudoku.Listen();
break;
}
} while (choose != 3);
}
}
}
推荐阅读