# 暗棋程式碼(peer to peer & UDP)
> 使用語言:C#
> 使用框架:.NET framework4.6.1
```csharp
using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace 網路暗棋
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap[] chessbmp = new Bitmap[33];//0~32
Bitmap[] blank = new Bitmap[2];//深色淺色的空白
Bitmap board;//棋盤的底色
Bitmap platebmp = new Bitmap(800, 400);//存棋盤800*400,每個棋子100*100
Bitmap move_platebmp = new Bitmap(800, 400);
int offsetx, offsety,original_x,original_y;
Graphics g;
int[,] chesstable = new int[5, 9]; //記錄目前棋子狀況,蓋棋為負,正棋為正,0為空,棋盤左上角為1,1
UdpClient u, s;
Thread th;
string myIP;
string enemyIP = "";
int enemy=1000;
string sendstr = "";
Boolean play = true;
int playchess = -1; //紅子 0 藍子 1 若還未確定(第一步)-1
private void loadbitmap()
{
chessbmp[0] = new Bitmap(網路暗棋.Properties.Resources.背面);
chessbmp[1] = new Bitmap(網路暗棋.Properties.Resources.帥);
chessbmp[2] = new Bitmap(網路暗棋.Properties.Resources.仕); chessbmp[3] = new Bitmap(網路暗棋.Properties.Resources.仕);
chessbmp[4] = new Bitmap(網路暗棋.Properties.Resources.相); chessbmp[5] = new Bitmap(網路暗棋.Properties.Resources.相);
chessbmp[6] = new Bitmap(網路暗棋.Properties.Resources.車); chessbmp[7] = new Bitmap(網路暗棋.Properties.Resources.車);
chessbmp[8] = new Bitmap(網路暗棋.Properties.Resources.傌); chessbmp[9] = new Bitmap(網路暗棋.Properties.Resources.傌);
chessbmp[10] = new Bitmap(網路暗棋.Properties.Resources.砲); chessbmp[11] = new Bitmap(網路暗棋.Properties.Resources.砲);
chessbmp[12] = new Bitmap(網路暗棋.Properties.Resources.兵); chessbmp[13] = new Bitmap(網路暗棋.Properties.Resources.兵);
chessbmp[14] = new Bitmap(網路暗棋.Properties.Resources.兵); chessbmp[15] = new Bitmap(網路暗棋.Properties.Resources.兵);
chessbmp[16] = new Bitmap(網路暗棋.Properties.Resources.兵);
chessbmp[17] = new Bitmap(網路暗棋.Properties.Resources.將);
chessbmp[18] = new Bitmap(網路暗棋.Properties.Resources.士); chessbmp[19] = new Bitmap(網路暗棋.Properties.Resources.士);
chessbmp[20] = new Bitmap(網路暗棋.Properties.Resources.象); chessbmp[21] = new Bitmap(網路暗棋.Properties.Resources.象);
chessbmp[22] = new Bitmap(網路暗棋.Properties.Resources.車藍); chessbmp[23] = new Bitmap(網路暗棋.Properties.Resources.車藍);
chessbmp[24] = new Bitmap(網路暗棋.Properties.Resources.馬); chessbmp[25] = new Bitmap(網路暗棋.Properties.Resources.馬);
chessbmp[26] = new Bitmap(網路暗棋.Properties.Resources.包); chessbmp[27] = new Bitmap(網路暗棋.Properties.Resources.包);
chessbmp[28] = new Bitmap(網路暗棋.Properties.Resources.卒); chessbmp[29] = new Bitmap(網路暗棋.Properties.Resources.卒);
chessbmp[30] = new Bitmap(網路暗棋.Properties.Resources.卒); chessbmp[31] = new Bitmap(網路暗棋.Properties.Resources.卒);
chessbmp[32] = new Bitmap(網路暗棋.Properties.Resources.卒);
blank[0] = new Bitmap(網路暗棋.Properties.Resources.blank0); blank[1] = new Bitmap(網路暗棋.Properties.Resources.blank1);
board = new Bitmap(網路暗棋.Properties.Resources.底板);
}
private void resetboard()
{
int[] temp = new int[33];
int tmp;
Random rnd = new Random();
for (int i=1;i<5;i++)
for (int j = 1; j < 9; j++)
{
do
tmp = rnd.Next(1, 33);
while (temp[tmp] == 1);
temp[tmp] = 1;
chesstable[i, j] = -tmp;
}
}
private void printboard()
{
for (int i = 1; i < 5; i++)
{
for (int j = 1; j < 9; j++)
Console.Write("{0,4}", chesstable[i, j] + " ");
Console.WriteLine();
}
}
private void redraw()
{
if (plate.Image != null) plate.Image.Dispose();
plate.Image = platebmp.Clone(new Rectangle(0, 0, platebmp.Width, platebmp.Height), platebmp.PixelFormat);
}
private string getmyIP()
{
string hn = Dns.GetHostName();
IPAddress[] ip = Dns.GetHostEntry(hn).AddressList;
for (int i = 0; i < ip.Length; i++)
if (ip[i].AddressFamily == AddressFamily.InterNetwork)
return ip[i].ToString();
return "";
}
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
myIP = getmyIP();
this.Text = myIP;
resetboard();
printboard();
loadbitmap();
g = Graphics.FromImage(platebmp);
g.DrawImage(board, new Rectangle(0, 0, 800, 400));
for (int i = 0; i < 4; i++)
for (int j = 0; j < 8; j++)
g.DrawImage(chessbmp[0], new Rectangle(j * 100, i * 100, 100, 100));
redraw();
}
private void button1_Click(object sender, EventArgs e)
{
enemyIP = EnemyPort.Text;
s = new UdpClient(enemyIP, 1000);
th = new Thread(listen);
th.Start();
button1.Enabled = false;
}
private void listen()
{
int self = 1000;
int x, y, ox, oy;
u = new UdpClient(self);
IPEndPoint EP = new IPEndPoint(IPAddress.Parse(myIP), self);
while (true)
{
byte[] bu = u.Receive(ref EP);
string[] cmd = Encoding.Default.GetString(bu).Split(',');
switch (cmd[0])
{
case "0":
for (int i = 0; i < 4; i++)
for (int j = 0; j < 8; j++)
g.DrawImage(chessbmp[0], new Rectangle(j * 100, i * 100, 100, 100));
redraw();
for (int i = 1; i < 33; i++)
chesstable[(i - 1) / 8 + 1, (i - 1) % 8 + 1] = int.Parse(cmd[i]);
play = true;
playchess = -1;
this.BackColor = Color.Yellow;
saybox.Text = "我先下!!" + "\n\r";
break;
case "1":
y = int.Parse(cmd[1]); x = int.Parse(cmd[2]);
oy = int.Parse(cmd[3]); ox = int.Parse(cmd[4]);
g.DrawImage(chessbmp[chesstable[oy, ox]], new Rectangle((x - 1)*100,(y - 1)*100,100,100));
g.DrawImage(blank[(ox + oy) % 2], new Rectangle((ox - 1) * 100, (oy - 1) * 100, 100, 100));
redraw();
chesstable[y, x] = chesstable[oy, ox];
chesstable[oy, ox] = 0;
play = true;
this.BackColor = Color.Yellow;
break;
case "2":
y = int.Parse(cmd[1]); x = int.Parse(cmd[2]);
chesstable[y, x] = -chesstable[y, x];
g.DrawImage(chessbmp[chesstable[y, x]], new Rectangle((x - 1) * 100, (y - 1) * 100, 100, 100));
redraw();
play = true;
this.BackColor = Color.Yellow;
break;
case "3":
y = int.Parse(cmd[1]);x = int.Parse(cmd[2]);
if (int.Parse(cmd[3])==0) { playchess = 1;this.Text = "藍棋"; } else { playchess = 0; this.Text = "紅棋"; }
chesstable[y, x] = -chesstable[y, x];
g.DrawImage(chessbmp[chesstable[y, x]], new Rectangle((x - 1) * 100, (y - 1) * 100, 100, 100));
redraw();
play = true;
this.BackColor = Color.Yellow;
break;
case "4":
saybox.Text = "對手說:" + cmd[1] + "\r\n" + saybox.Text;
break;
}
}
}
private void send(string str)
{
byte[] bs = Encoding.Default.GetBytes(str);
s.Send(bs, bs.Length);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if(th!=null) th.Abort();
if (u!=null) u.Close();
if (s != null) s.Close();
}
private void msgbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
saybox.Text = "我說:" + msgbox.Text + "\r\n" + saybox.Text;
send("4," + msgbox.Text);
msgbox.Text = "";
}
}
private void restart_Click(object sender, EventArgs e)
{
resetboard();
for(int i = 0; i < 4; i++)
for (int j = 0; j < 8; j++)
g.DrawImage(chessbmp[0], new Rectangle(j * 100, i * 100, 100, 100));
redraw();
sendstr = "0";
for (int i = 1; i < 5; i++)
for (int j = 1; j < 9; j++)
sendstr += "," + chesstable[i, j];
send(sendstr);
Console.WriteLine(sendstr);
play = false;
playchess = -1;
this.BackColor = Color.Ivory;
saybox.Text = "";
}
private void plate_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && play )
{
if (chesstable[original_y / 100 + 1, original_x / 100 + 1]>0)
{
g.DrawImage(move_platebmp, new Rectangle(0, 0, 800, 400));
g.DrawImage(chessbmp[chesstable[original_y / 100 + 1, original_x / 100 + 1]], new Rectangle(e.X - offsetx, e.Y - offsety, 100, 100));
redraw();
}
}
}
private Boolean movable(int y,int x,int y1,int x1)
{
int self = chesstable[y1 / 100 + 1, x1 / 100 + 1];
int enemy = chesstable[y / 100 + 1, x / 100 + 1];
if ((self - 1) / 16 != playchess) return false;
if (y >= 400 || x >= 800 || y < 0 || x < 0) return false;
if (y == y1 && x == x1) return false;
if ((self == 26 || self == 27 || self == 10 || self == 11) && enemy > 0 && Math.Abs(enemy / 17 - self / 17) == 1)
{
if (Math.Abs(y1 - y) == 100 && Math.Abs(x1 - x) == 0 || Math.Abs(y1 - y) == 0 && Math.Abs(x1 - x) == 100) { return false; }
int count = 0;
if (x1 / 100 == x / 100) //同一行
{
if (y / 100 > y1 / 100)
{//向下
for (int i = y1 / 100 + 1; i <= y / 100 + 1; i++)
if (chesstable[i, x / 100 + 1] != 0) count++;
}
else
{//向上
for (int i = y1 / 100 + 1; i>= y / 100 + 1; i--)
if (chesstable[i, x / 100 + 1] != 0) count++;
}
if (count == 3) return true;
}
if (y1 / 100 == y / 100)//同一列
{
if (x / 100 > x1 / 100)
{//向右
for (int i = x1 / 100 + 1; i <= x / 100 + 1; i++)
if (chesstable[y / 100 + 1, i] != 0) count++;
}
else
{//向左
for (int i = x1 / 100 + 1; i >= x / 100 + 1; i--)
if (chesstable[y / 100 + 1, i] != 0) count++;
}
if (count == 3) return true;
}
}
if (Math.Abs(y1-y)==100 && Math.Abs(x1-x)==0 || Math.Abs(y1-y)==0 && Math.Abs(x1-x)==100)
{
if (enemy < 0) return false;
if (enemy == 0) return true;
if (enemy >0 && Math.Abs(self / 17 - enemy / 17) == 1)
{
if (enemy > 16) enemy -= 16;
if (self > 16) self -= 16;
if (self >= 12 && self <= 16 && enemy >= 12 && enemy <= 16) return true;
if (self >= 12 & self <= 16 && enemy == 1) return true;
if (self == 1 && enemy >= 12 && enemy <= 16) return false;
if (self / 2 <= enemy / 2) return true;
}
} else return false;
return false;
}
private void plate_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && play )
{
int x = e.X / 100 * 100;
int y = e.Y / 100 * 100;
if (chesstable[original_y / 100 + 1, original_x / 100 + 1] > 0)
{
if (movable(y, x, original_y, original_x))
{
g.DrawImage(move_platebmp, new Rectangle(0, 0, 800, 400));
g.DrawImage(chessbmp[chesstable[original_y / 100 + 1, original_x / 100 + 1]], new Rectangle(x, y, 100, 100));
redraw();
chesstable[y / 100 + 1, x / 100 + 1] = chesstable[original_y / 100 + 1, original_x / 100 + 1];
chesstable[original_y / 100 + 1, original_x / 100 + 1] = 0;
send("1," +( y / 100 + 1) + "," + (x / 100 + 1) + "," + (original_y / 100 + 1) + "," + (original_x / 100 + 1));
//1,目標位置Y,目標位置X,來源為至Y,來源位置X
play = false;
this.BackColor = Color.Ivory;
}
else
{
g.DrawImage(move_platebmp, new Rectangle(0, 0, 800, 400));
g.DrawImage(chessbmp[chesstable[original_y / 100 + 1, original_x / 100 + 1]], new Rectangle(original_x, original_y, 100, 100));
redraw();
}
}
else if (chesstable[y / 100 + 1, x / 100 + 1] < 0)
{
chesstable[y / 100 + 1, x / 100 + 1] = -chesstable[y / 100 + 1, x / 100 + 1];
g.DrawImage(chessbmp[chesstable[y / 100 + 1, x / 100 + 1]], new Rectangle(x, y, 100, 100));
redraw();
if (playchess == -1)
{
if (chesstable[y / 100 + 1, x / 100 + 1] >= 1 && chesstable[y / 100 + 1, x / 100 + 1] <= 16)
{ playchess = 0; this.Text = "紅棋"; }//Red
else
{ playchess = 1; this.Text = "藍棋"; }//Blue
send("3," + (y / 100 + 1) + "," + (x / 100 + 1)+"," + playchess);
}
else
{
send("2," + (y / 100 + 1) + "," + (x / 100 + 1));
}
play = false;
this.BackColor = Color.Ivory;
}
}
}
private void plate_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && play )
{
int x = e.X / 100 * 100;
int y = e.Y / 100 * 100;
original_x = x;
original_y = y;
if (chesstable[y/100+1,x/100+1] > 0)
{
offsetx = e.X - x;
offsety = e.Y - y;
g.DrawImage(blank[(x / 100 + y / 100) % 2], new Rectangle(x, y, 100, 100));
move_platebmp = platebmp.Clone(new Rectangle(0, 0, 800, 400), platebmp.PixelFormat);
g.DrawImage(chessbmp[chesstable[y / 100 + 1, x / 100 + 1]], new Rectangle(x, y, 100, 100));
redraw();
}
}
}
}
}
```