2048 ゲームのルールは比較的単純です。プレイヤーはキューブの動きを上下左右の 4 方向に操作します。移動するたびに、すべてのキューブがこの方向に移動します。このとき、キューブはすべてその方向に移動します。ランダムな空き領域に新しいデジタルブロックを生成します 移動中、そのブロックの番号が進行方向にある次のブロックの番号と同じ場合、新しいブロックに衝突します その番号は次のブロックの合計です2 つのブロック番号。すべての場所がマスで埋まり、各マスと隣接するマスの間の数字が同じでない場合、ゲームは終了します。
操作結果:
必要なコントロール: ゲームをリセットするボタン、スコアを表示する 2 つのラベル、およびリアルタイムの数値を表示する 16 個のテキストボックスを保持するパネル コンテナー。
上記の状況が発生した場合は、各テキストボックスの TabStop プロパティを false に変更するか、テキストボックスの代わりにラベルを使用してください。
このプログラムはW、A、S、Dの4つのキーを使ってブロックの移動を操作します。Form1 の KeyPreview プロパティを true に変更することを忘れないでください。
まず変数を定義します
public class Variables
{
public static int score; //分数
public static int[] Num = new int[16];
public static int[,] TempNum = new int[4, 4]; //移动
public static int[] num = new int[16];
}
このプログラムは、長さ 16 の配列を使用して、各正方形 (つまり、各テキストボックス) の番号を格納します。
移動方法:
public void MovingW()
{
for (int i = 0; i < 4; i++)
{
ArrayList arr = new ArrayList();
//将某一列所有不为0的元素的索引找出来
for (int j = 0; j < 4; j++)
{
if (Num[i+j*4] != 0)
{
arr.Add(j);
}
}
if (arr.Count == 1)
{
TempNum[0, i] = Num[i+Convert.ToInt32(arr[0])*4];
TempNum[1, i] = 0;
TempNum[2, i] = 0;
TempNum[3, i] = 0;
}
if (arr.Count == 2)
{
if (Num[Convert.ToInt32(arr[0])*4+i] == Num[Convert.ToInt32(arr[1])*4+i])
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+i] + Num[Convert.ToInt32(arr[1])*4+i];
TempNum[1, i] = 0;
TempNum[2, i] = 0;
TempNum[3, i] = 0;
score += (TempNum[0, i]) / 2;
}
else
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+i];
TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+i];
TempNum[2, i] = 0;
TempNum[3, i] = 0;
}
}
if (arr.Count == 3)
{
if (Num[Convert.ToInt32(arr[0])*4+i] == Num[Convert.ToInt32(arr[1])*4+i])
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+i] + Num[Convert.ToInt32(arr[1])*4+i];
TempNum[1, i] = Num[Convert.ToInt32(arr[2])*4+ i];
TempNum[2, i] = 0;
TempNum[3, i] = 0;
score += (TempNum[0, i]) / 2;
}
else
{
if (Num[Convert.ToInt32(arr[1])*4+i] == Num[Convert.ToInt32(arr[2])*4+i])
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i] + Num[Convert.ToInt32(arr[2])*4+ i];
TempNum[2, i] = 0;
TempNum[3, i] = 0;
score += (TempNum[1, i]) / 2;
}
else
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i];
TempNum[2, i] = Num[Convert.ToInt32(arr[2])*4+ i];
TempNum[3, i] = 0;
}
}
}
if (arr.Count == 4)
{ if (Num[Convert.ToInt32(arr[0])*4+ i] == Num[Convert.ToInt32(arr[1])*4+ i])
{
if (Num[Convert.ToInt32(arr[2])*4+ i] == Num[Convert.ToInt32(arr[3])*4+ i])
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i] + Num[Convert.ToInt32(arr[1])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[2])*4+ i] + Num[Convert.ToInt32(arr[3])*4+ i];
TempNum[2, i] = 0;
TempNum[3, i] = 0;
score += (TempNum[0, i] + TempNum[1, i]) / 2;
}
else
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i] + Num[Convert.ToInt32(arr[1])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[2])*4+ i];
TempNum[2, i] = Num[Convert.ToInt32(arr[3])*4+ i];
TempNum[3, i] = 0;
score += (TempNum[0, i]) / 2;
}
}
else
{
if (Num[Convert.ToInt32(arr[1])*4+ i] == Num[Convert.ToInt32(arr[2])*4+ i])
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i] + Num[Convert.ToInt32(arr[2])*4+ i];
TempNum[2, i] = Num[Convert.ToInt32(arr[3])*4+ i];
TempNum[3, i] = 0;
score += (TempNum[1, i]) / 2;
}
else
{
if (Num[Convert.ToInt32(arr[2])*4+ i] == Num[Convert.ToInt32(arr[3])*4+ i])
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i];
TempNum[2, i] = Num[Convert.ToInt32(arr[2])*4+ i] + Num[Convert.ToInt32(arr[3])*4+ i];
TempNum[3, i] = 0;
score += (TempNum[2, i]) / 2;
}
else
{
TempNum[0, i] = Num[Convert.ToInt32(arr[0])*4+ i];
TempNum[1, i] = Num[Convert.ToInt32(arr[1])*4+ i];
TempNum[2, i] = Num[Convert.ToInt32(arr[2])*4+ i];
TempNum[3, i] = Num[Convert.ToInt32(arr[3])*4+ i];
}
}
}
}
}
}
これが上向きの移動方法、つまりWです。移動の結果は、正方行列の各列のゼロ以外の数値の数とそれらの等しいかどうかに基づいて計算され、加算する正方形がある場合にのみスコアが生成されます。他の 3 つの方向も同様であるため、ここでは繰り返しません。
ゲームが終了したかどうかを判断する
public bool GameOver()
{
bool over1 = false;
//判断格子是否已满
for (int i = 0; i < Num.Length; i++)
{
if (Num[i] == 0)
over1 = true;
}
//判断是否有相邻相同的
//四个角
if (Num[0] == Num[1] || Num[0] == Num[4] || Num[3] == Num[2] || Num[3] == Num[7]
|| Num[12] == Num[8] || Num[12] == Num[13] || Num[15] == Num[14] || Num[15] == Num[11])
over1 = true;
//四条边
int[] lines1 = { 1, 2, 4, 8, 7, 11, 13, 14 };
foreach (int i in lines1)
{
switch (i)
{
case 1:
case 2:
if (Num[i] == Num[i - 1] || Num[i] == Num[i + 1] || Num[i] == Num[i + 4])
over1 = true;
break;
case 4:
case 8:
if (Num[i] == Num[i - 4] || Num[i] == Num[i + 1] || Num[i] == Num[i + 4])
over1 = true;
break;
case 7:
case 11:
if (Num[i] == Num[i - 4] || Num[i] == Num[i - 1] || Num[i] == Num[i + 4])
over1 = true;
break;
case 13:
case 14:
if (Num[i] == Num[i - 1] || Num[i] == Num[i - 4] || Num[i] == Num[i + 1])
over1 = true;
break;
default:
break;
}
}
//中间四块
if (Num[5] == Num[6] || Num[6] == Num[10] || Num[5] == Num[9] || Num[9] == Num[10])
over1 = true;
return over1;
}
ゲーム終了のルールは、正方行列が塗りつぶされ、隣接する 2 つの数字が存在しないことです。
まず正方行列が満たされているかどうかを判断し、Num の数字が 1 つだけ 0 であれば、ゲームは続行されます。
次に、隣接する状況を判断します。正方行列内の各位置の隣接状況が異なるため、個別に議論する必要があります。
まず、2 つの正方形に隣接する 4 つの角の隣接関係を調べます。次に、各辺の中央の 2 つは 3 つの正方形に隣接します。最後に、中央の 4 つはすべて 4 つの正方形に隣接しています。これらの隣接するケースのうち 1 つだけが true、つまり戻り値が true であり、ゲームは終了しません。
プログラムがロードされるとき
private void Form1_Load(object sender, EventArgs e)
{
label2.Text = "0";
//随机赋初值
Random r = new Random();
int k = r.Next(0, Num.Length);
Num[k] = 2;
timer1.Start();
MessageBox.Show("开始!");
}
プログラムがロードされると、初期スコアは 0 で、正方行列内に数値「2」がランダムに生成されます。タイマーは、Num 配列の値をテキスト ボックスに割り当て、リアルタイムで表示を更新するために使用されます。ここでは、テキストボックスのさまざまな値に応じてさまざまな背景色を設定して、簡単に区別できます。
private void timer1_Tick(object sender, EventArgs e)
{
#region 数字显示
if (Num[0] != 0)
textBox1.Text = Num[0].ToString();
if (Num[1] != 0)
textBox2.Text = Num[1].ToString();
if (Num[2] != 0)
textBox3.Text = Num[2].ToString();
if (Num[3] != 0)
textBox4.Text = Num[3].ToString();
if (Num[4] != 0)
textBox5.Text = Num[4].ToString();
if (Num[5] != 0)
textBox6.Text = Num[5].ToString();
if (Num[6] != 0)
textBox7.Text = Num[6].ToString();
if (Num[7] != 0)
textBox8.Text = Num[7].ToString();
if (Num[8] != 0)
textBox9.Text = Num[8].ToString();
if (Num[9] != 0)
textBox10.Text = Num[9].ToString();
if (Num[10] != 0)
textBox11.Text = Num[10].ToString();
if (Num[11] != 0)
textBox12.Text = Num[11].ToString();
if (Num[12] != 0)
textBox13.Text = Num[12].ToString();
if (Num[13] != 0)
textBox14.Text = Num[13].ToString();
if (Num[14] != 0)
textBox15.Text = Num[14].ToString();
if (Num[15] != 0)
textBox16.Text = Num[15].ToString();
#endregion
#region 设置字体及颜色
foreach (Control ctr in panel1.Controls)
{
if (ctr is TextBox)
{
ctr.Font = new Font("宋体", 12, ctr.Font.Style);
ctr.ForeColor = Color.Black;
switch (ctr.Text)
{
case "":
ctr.BackColor = Color.White;
break;
case "2":
ctr.BackColor = Color.Blue;
break;
case "4":
ctr.BackColor = Color.Pink;
break;
case "8":
ctr.BackColor = Color.Orange;
break;
case "16":
ctr.BackColor = Color.Gray;
break;
case "32":
ctr.BackColor = Color.Green;
break;
case "64":
ctr.BackColor = Color.Brown;
break;
case "128":
ctr.BackColor = Color.Goldenrod;
break;
case "256":
ctr.BackColor = Color.LightBlue;
break;
case "512":
ctr.BackColor = Color.Violet;
break;
case "1024":
ctr.BackColor = Color.Yellow;
break;
case "2048":
ctr.BackColor = Color.MediumTurquoise;
break;
}
}
}
#endregion
label2.Text = score.ToString();
}
移動前後の正方行列を比較、つまりMovingメソッドを呼び出す前後のNumを比較し、異なる場合は正方行列を移動した後、正方行列が移動した箇所にランダムに2か4を生成するこのとき、 は空、つまり値は 0 です。 それらが同じである場合、新しい番号は生成されません。
public int[] NewNumber()
{
Random a = new Random();
int i;
ArrayList arr = new ArrayList { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, }; //生成数的范围,2多4少
int[] Select;
Select = ArraylistToInt(arr); //list转int数组
i = GetOneIndex(Num); //在Num中随机得到一个索引即生成的位置
if (i != 99)
Num[i] = GetOneNumber(Select);
return Num;
}
public int GetOneNumber(int[] arr) //在数组中随机获得一个数
{
Random index = new Random();
int i;
if (arr.Length == 1)
i = 0;
else
i = index.Next(0, arr.Length);
return arr[i];
}
public int GetOneIndex(int[] a) //在数组中随机得到一个为0的索引
{
ArrayList arr = new ArrayList();
for (int i = 0; i < a.Length; i++)
{
if (a[i] == 0)
{
arr.Add(i);
}
}
Random r = new Random();
int k;
if (arr.Count == 0)
{ k = 99; }
else
{
if (arr.Count == 1)
k = 0;
else
k = r.Next(0, arr.Count);
}
return (int)arr[k];
}
public int[] ArraylistToInt(ArrayList arr)
{
int[] s = new int[arr.Count];
for (int i = 0; i < arr.Count; i++)
{
s[i] = Convert.ToInt16(arr[i]);
}
return s;
}
//判断运动前后是否相同
for(int i=0;i<Num.Length;i++)
{
if(num[i]!=Num[i])
{
method.NewNumber();
break;
}
}
各演習が完了したら、上記のタイマーの内容と同様の新しいタイマーを入力する必要がありますが、タイマーを入力するたびにテキスト ボックスの内容をクリアして表示するだけで済みます。ゲームオーバーかどうかの判定を加えればOK。
//清空文本框内容
foreach (Control ctrl in panel1.Controls)
{
if (ctrl is TextBox)
{
ctrl.Text = "";
}
}
//
//跟timer1中的显示和颜色字体设置一样
//
//判断游戏是否结束
if (quiit== false)
{
quiit = true;
MessageBox.Show("gameover", "失败");
}