游戏玩法:
随机四位数,每猜一次,就会根据猜的数字给出几A几B,
其中A前面的数字表示位置正确的数的个数,
而B前的数字表示数字正确而位置不对的数的个数。
获胜条件:4A0B
如正确答案为5543,
猜的人猜5255,
则在这里不能认为猜测的第一个5对正确答案第二个,
根据最优结果为准的原理和每个数字只能有一次的规则,两个比较后应该为1A1B
ps:游戏规则其实是四位不重复数字的,但是我觉得猜起来太简单,弄了个可重复的,
导致判断几A几B的逻辑变的更难,数字不重复的判断我都写出来了,想了好久也没想到怎么写判断重复的
我苦思冥想,终于想到了解决方法,就是写一个数组,用来标记。
接下来上代码和窗体界面
窗体界面
右边有5个按钮,分别为 开始游戏、重新开始、游戏规则、退出、确认
数字和删除键也都是按钮、backcolor设为白色
拖三个 Label 控件,用来提示次数,几A几B,和输入的数字
我用的是4个label显示数字,大家根据喜好设置
窗体代码(控件的点击(Click)方法等等)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace day11_02
{
public partial class Form1 : Form
{
public static Form1 form; // 创建一个可以在其他类调用的窗口属性
private bool start; // 是否开始游戏
private String[] EnterNum = new String[4]; // 输入的数字数组,下标0-3,千 百 十 个
private String[] GuessNum = new String[4]; // 要猜的数字数组,下标0-3,千 百 十 个
private int[] SignGuessNum = new int[4]{0, 0, 0, 0}; // 标记要猜的数字,默认都是0,0代表没被匹配,1代表数字被匹配,2代表位置被匹配
int Chance = 0; // 机会
public Form1()
{
InitializeComponent();
form = this; // 窗口赋值给创建的窗口属性
}
private void Form1_Load(object sender, EventArgs e)
{
initializeGame(); // 调用初始化游戏
this.Width = 560; // 设置窗口宽度
this.Height = 510; // 设置窗口高度
this.Location = new Point(400, 75); // 设置窗口位置
}
// 初始化游戏
private void initializeGame()
{
// 清空输入的数字数组
for (int i = 0; i < EnterNum.Length; i++)
{
EnterNum[i] = null;
}
Num.ShowNum(EnterNum); // 调用显示数字方法
start = false; // 未开始
LblTips.Text = "游戏未开始"; // 提示改为"游戏未开始"
button16.Visible = true; // 显示'开始游戏'按钮
button15.Visible = false; // 隐藏'重新开始'按钮
}
// 按钮“开始游戏”的Click事件
private void button16_Click(object sender, EventArgs e)
{
start = true; // 开始
label8.Text = Convert.ToString(Chance = 7); // 次数设为7,并提示
GuessNum = Num.RepeatRandomNum(GuessNum);// 随机四位数
LblTips.Text = "0A0B"; // 提示改为"0A0B"
button16.Visible = false; // 隐藏'开始游戏'按钮
button15.Visible = true; // 显示'重新开始'按钮
}
// 按钮“重新开始”的Click事件
private void button15_Click(object sender, EventArgs e)
{
// 确认是否重新开始
if (MessageBox.Show("确认要重新开始?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK)
{
initializeGame(); // 调用初始化游戏方法
button16_Click(sender, e); // 调用按钮“开始游戏”的Click事件
}
}
// 按钮“游戏规则”的Click事件
private void button12_Click(object sender, EventArgs e)
{
MessageBox.Show("随机四位数,每猜一次,就会根据猜的数字给出几A几B,\n其中A前面的数字表示位置正确的数的个数,\n而B前的数字表示数字正确而位置不对的数的个数。\n获胜条件:4A0B\t7次机会", "提示");
MessageBox.Show("如正确答案为5543,\n猜的人猜5255,\n则在这里不能认为猜测的第一个5对正确答案第二个,根据最优结果为准的原理和每个数字只能有一次的规则,两个比较后应该为1A1B");
}
// 按钮“确认”的Click事件
private void button13_Click(object sender, EventArgs e)
{
// 判断有没有开始游戏
if (start)
{
// 判断个位有没有数字,没有就结束事件
if (EnterNum[3] == null)
{
MessageBox.Show("输入四位数", "提示");
return; // 结束事件
}
label8.Text = Convert.ToString(--Chance); // 次数减1,并提示
// 更新提示
LblTips.Text = Judgment.Tips(String.Join("", GuessNum), String.Join("", EnterNum), SignGuessNum);
// 通过提示判断胜利
if (LblTips.Text.Equals("4A0B"))
{
MessageBox.Show("还剩" + Chance + "次机会时,你猜对了!", "提示");
initializeGame(); // 调用初始化方法
return; // 结束事件
}
// 次数为0时,提示
if (Chance == 0)
{
MessageBox.Show("次数不足,挑战失败\n\n正确答案为:" + string.Join("", GuessNum), "提示");
initializeGame(); // 调用初始化方法
}
}
else
{
MessageBox.Show("请先开始游戏!", "提示");
}
}
// 按钮“退出”的Click事件
private void button14_Click(object sender, EventArgs e)
{
this.Dispose(); // 关闭并销毁窗体
}
// 按钮“数字键”的Click事件
// 所有数字键的同一个点击事件
private void btn_1_Click(object sender, EventArgs e)
{
// 判断游戏是否开始
if (start == false)
{
MessageBox.Show("请先开始游戏!", "提示");
return;
}
// 调用Num类的"添加数字方法"
// 传入[输入数字的数组,和当前控件(数字按钮)的Text值]
Num.AddNum(EnterNum, ((Button)sender).Text);
}
// 按钮“退格”的Click事件
private void button11_Click(object sender, EventArgs e)
{
if (start == false)
{
MessageBox.Show("请先开始游戏!", "提示");
return;
}
// 判断千位有没有数字,没有数字就结束事件
if (EnterNum[0] == null)
{
return; // 结束事件
}
// 遍历输入的数字数组
for (int i = EnterNum.Length - 1; i >= 0; i--)
{
// 从个位开始判断,有没有数字,没有数字就跳过循环
if (EnterNum[i] == null)
{
continue; // 跳过本轮循环
}
EnterNum[i] = null; // 清除数字
Num.ShowNum(EnterNum); // 调用显示数字方法
break; // 结束遍历
}
}
}
}
数字类 代码(添加输入数字,显示输入数字,随机四位数字)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace day11_02
{
// 数字类
class Num
{
// 显示数字方法
public static void ShowNum(String[] EnterNum)
{
Form1.form.label2.Text = EnterNum[0]; // 显示千位
Form1.form.label3.Text = EnterNum[1]; // 显示百位
Form1.form.label4.Text = EnterNum[2]; // 显示十位
Form1.form.label5.Text = EnterNum[3]; // 显示个位
}
// 添加数字方法
public static void AddNum(String[] EnterNum, String Digit)
{
// 判断个位有没有数字,有数字就结束方法
if (EnterNum[3] != null)
{
return; // 结束方法
}
// 遍历输入的数字数组
for (int i = 0; i < EnterNum.Length; i++)
{
// 从千位开始判断,有没有数字,没有就添加数字
if (EnterNum[i] == null)
{
EnterNum[i] = Digit; // 添加数字
Num.ShowNum(EnterNum); // 调用显示数字方法
break; // 结束遍历
}
}
}
// 随机四位可重复数字方法
public static String[] RepeatRandomNum(String[] GuessNum)
{
Random r = new Random(); // 实例化随机数生成器
// 随机四位数字
for (int i = 0; i < GuessNum.Length; i++)
{
string RandomStr = r.NextDouble().ToString(); // 返回一个随机数,并转换为字符串
GuessNum[i] = RandomStr.Substring(RandomStr.Length - 2, 1); // 截取最后一位数字给数组
}
return GuessNum; // 返回数组
}
}
}
裁判类 代码(刷新提示,提示用来判断胜利)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace day11_02
{
// 判断(裁判)
class Judgment
{
// 刷新提示,并用来判断胜利
public static string Tips(String GuessNum, String EnterNum, int[] SignGuessNum)
{
// 保存A的数量
int ANum = 0;
// 保存要猜的数字与输入的数字的各个数字的数量,不保存A的数字
int[] cntG = new int[10];
int[] cntE = new int[10];
// 遍历两个数字
for (int i = 0; i < 4; i++)
{
// 数字与位置相同,则A的数量+1
if (GuessNum[i] == EnterNum[i])
{
ANum++;
}
// 数字不同,则统计数量
else
{
cntG[GuessNum[i] - '0']++;
cntE[EnterNum[i] - '0']++;
}
}
// 保存B的数量
int BNum = 0;
// B的数量为分别统计的相同数字的最小值,即多余的没有匹配,不为B
for (int i = 0; i < 10; i++)
{
BNum += Math.Min(cntG[i], cntE[i]);
}
return ANum + "A" + BNum + "B";
}
}
}
效果图:
ps: 我觉得7次机会太难了,你们可以多加点次数。
因为可以重复,确实不好猜哈哈哈哈哈
另一个窗体小游戏:五子棋