日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

GOBang对战

發(fā)布時(shí)間:2025/4/9 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GOBang对战 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、學(xué)習(xí)目標(biāo)

參考可以通過(guò)因特網(wǎng)對(duì)弈的“吃棋子”游戲程序,按以下要求進(jìn)行改編,要求如下:

1)將游戲改為雙方對(duì)弈,而不是系統(tǒng)自動(dòng)下棋;

2)修改游戲規(guī)則,如五子棋的游戲規(guī)則;

3)同步改異步;

?

二、設(shè)計(jì)思路

1)放置棋子。先不考慮輪流下子的情況和輸贏的問(wèn)題,重新把服務(wù)器端和客戶端的發(fā)送信息和處理收到的信息處理一次。

客戶端:修改玩家對(duì)鼠標(biāo)點(diǎn)擊的事件處理,設(shè)置顏色color變量屬性表示玩家下的棋子的顏色,和side變量相同,下的棋子的顏色會(huì)相同,在下棋的地方會(huì)出現(xiàn)玩家相應(yīng)顏色的棋子。

private int color; //edit this.color = side;

/// <summary>在pictureBox1中按下鼠標(biāo)觸發(fā)的事件</summary>

??????? private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

??????? {

??????????? int x = e.X / 20;

??????????? int y = e.Y / 20;

??????????? if (!(x < 1 || x > 15 || y < 1 || y > 15))

??????????? {

??????????????? if (grid[x - 1, y - 1] == DotColor.None)//edit

??????????????? {

??????????????????? //int color = (int)grid[x - 1, y - 1];

??????????????????? //發(fā)送格式:setDot,桌號(hào),座位號(hào),行,列,顏色

?????????????????? ?service.SendToServer(string.Format(

?????????????????????? "SetDot,{0},{1},{2},{3},{4}", tableIndex, side, x - 1, y - 1, this.color));//edit

??????????????? }

??????????? }

??????? }

服務(wù)器端,去掉課本例子中根據(jù)事件間隔隨機(jī)交替的發(fā)送兩種顏色的棋子那部分功能。每當(dāng)一方玩家下棋后,給同桌的玩家兩人發(fā)送新的棋子的位置。

public int turn;?????????????????? //輪流玩,0為黑,1為白

/// <summary>發(fā)送產(chǎn)生的棋子信息</summary>

??????? /// <param name="i">指定棋盤的第幾行</param>

??????? /// <param name="j">指定棋盤的第幾列</param>

??????? /// <param name="dotColor">棋子顏色</param>

??????? public void SetDot(int i, int j, int dotColor)//edit private to public

??????? {

??????????? if (dotColor == turn)//edit

??????????? {

??????????????? //向兩個(gè)用戶發(fā)送產(chǎn)生的棋子信息,并判斷是否有相鄰棋子

??????????????? //發(fā)送格式:SetDot,行,列,顏色

??????????????? grid[i, j] = dotColor;

??????????????? service.SendToBoth(this, string.Format("SetDot,{0},{1},{2}", i, j, dotColor));

??????????????? if (win(dotColor))//edit

??????????????? {

??????????????????? ShowWin(dotColor);

??????????????? }

??????????????? turn = (turn + 1)%2;

??????????? }

??????? }

?

2)解決輸贏判斷的問(wèn)題。五子棋游戲的規(guī)則為是先有相同顏色的五子相連的那方的玩家贏,棋子可以按照橫豎斜三個(gè)方向,但是考慮邊界的情況。

修改游戲勝利的條件。每當(dāng)一個(gè)玩家下子完畢后就判斷。GameTable類中更改勝利條件

//是否勝利。

??????? private bool win(int dotColor)//edit

??????? {

??????????? int num = 15;

??????????? int checkPoint = 0;

??????????? int i = 0;

??????????? int j = 0;

??????????? //橫著檢查。

??????????? for (int x = 0; x < num * num; x++)

??????????? {

??????????????? int consecutive = 0;

??????????????? checkPoint = x;

??????????????? for (int y = 0; y < 5; y++)

??????????????? {

??????????????????? i = (checkPoint + y) % num;

??????????????????? j = (int)checkPoint / num;

??????????????????? if (checkPoint > (num * num - 1) || i > num - 1)

??????????????????????? break;

??????????????????? if (grid[i, j] == dotColor)

??????????????????? {

??????????????????????? consecutive++;

??????????????????? }

??????????????????? //checkPoint++;

??????????????? }

??????????????? if (consecutive == 5)

??????????????????? return true;

??????????? }

??????????? //豎著檢查

??????????? for (int x = 0; x < num * num; x++)

??????????? {

??????????????? int consecutive = 0;

??????????????? checkPoint = x;

??????????????? for (int y = 0; y < 5; y++)

??????????????? {

??????????????????? i = (checkPoint + y) % num;

??????? ????????????j = (int)checkPoint / num;

??????????????????? if (checkPoint > (num * num - 1) || i > num - 1)

??????????????????????? break;

??????????????????? if (grid[j, i] == dotColor)

??????????????????? {

??????????????????????? consecutive++;

??????? ????????????}

??????????????????? //checkPoint++;

??????????????? }

??????????????? if (consecutive == 5)

??????????????????? return true;

??????????? }

??????????? //正斜

??????????? for (int x = 0; x < num * num; x++)

??????????? {

??????????????? int consecutive = 0;

??????????????? checkPoint = x;

??????????????? for (int y = 0; y < 5; y++)

??????????????? {

??????????????????? i = checkPoint % num + y;

??????????? ????????j = ((int)checkPoint / num) + y;

??????????????????? if (i > num - 1 || j > num - 1)

??????????????????????? break;

??????????????????? if (grid[i, j] == dotColor)

??????????????????? {

??????????????????????? consecutive++;

??????????????????? }

??????????????? }

??????????????? if (consecutive == 5)

??????????????????? return true;

??????????? }

??????????? //反斜

??????????? for (int x = 0; x < num * num; x++)

??????????? {

??????????????? int consecutive = 0;

??????????????? checkPoint = x;

??????????????? for (int y = 0; y < 5; y++)

??????????????? {

??????????????????? i = checkPoint % num - y;

??????????? ????????j = (int)checkPoint / num + y;

??????????????????? if (i > num - 1 || i < 0 || j > num - 1 || j < 0)

??????????????????????? break;

??????????????????? if (grid[i, j] == dotColor)

??????????????????? {

??????????????????????? consecutive++;

?????? ?????????????}

??????????????? }

??????????????? if (consecutive == 5)

??????????????????? return true;

??????????? }

??????????? return false;

??????? }

?

勝利后的提示信息改為

case "win":

??????????????????????? //格式:Win,相鄰棋子的顏色,黑方成績(jī),白方成績(jī)

??????????????????????? string winner = "";

??????????????????????? if ((DotColor)int.Parse(splitString[1]) == DotColor.Black)

??????????????????????? {

??????????????????????????? winner = "黑方出現(xiàn)五子相連,黑方勝利!";//edit

??????????????????????? }

??????????????????????? else

??????????????????????? {

??????????????????????????? winner = "白方出現(xiàn)五子相連,白方勝利!";//edit

??????????????????????? }

??????????????????????? formPlaying.ShowMessage(winner);

??????????????????????? formPlaying.Restart(winner);

??????????????????????? break;

?

?

3)雙方輪流的下棋子。在雙方都開始后游戲正式開始。

在前面代碼中已經(jīng)添加了turn變量,控制下棋方玩家。初始化的時(shí)候是-1,表示如果雙方?jīng)]有開始游戲,都不能下子。FormServer類收到的message處理start時(shí),更改條件,都開始后,把turn改為0,表示黑子先下,符合五子棋規(guī)則。關(guān)鍵代碼如下:

if (gameTable[tableIndex].gamePlayer[anotherSide].started == true)

??????????????????????? {

??????????????????????????? gameTable[tableIndex].ResetGrid();

??????????????????????????? //gameTable[tableIndex].StartTimer();

??????????????????????????? gameTable[tableIndex].Turn = 0;

??????????????????????? }

GameTable中,只有當(dāng)輪到自己時(shí),即到自己的顏色時(shí)才能下子。

public int Turn{

??????????? get{return turn;}

??????????? set { turn = value; }

??????? }

下子后,變換下子方。

turn = (turn + 1)%2;

?

4)同步改異步

程序在調(diào)用Begin…后,可以在調(diào)用線程上繼續(xù)執(zhí)行其下面的指令,同時(shí)異步操作在另一個(gè)線程上執(zhí)行。Begin…方法開始異步操作,并返回一個(gè)實(shí)現(xiàn) IAsyncResult接口的對(duì)象。IAsyncResult對(duì)象存儲(chǔ)有關(guān)異步操作的狀態(tài)信息。這些信息包括:IAsyncState:可選的特定的對(duì)象,包含異步操作需要的信息。syncWaitHandle:用于在異步操作完成前阻止程序執(zhí)行。CompletedSynchronously:指示異步操作是否在用于調(diào)用Begin…的線程上完成,而不是在單獨(dú)的ThreadPool線程上完成。IsCompleted:一個(gè)布爾值,指示異步操作是否已完成。

服務(wù)器端:監(jiān)聽客戶端和接收客戶端消息類似,使用異步方式調(diào)用同步方法,通過(guò)輪詢方式檢查異步調(diào)用是否完成,使用EndInvoke結(jié)束異步調(diào)用,EndInvoke方法用于檢索異步調(diào)用的結(jié)果,并結(jié)束異步調(diào)用。調(diào)用BeginInvoke之后,隨時(shí)可以調(diào)用該方法。如果異步調(diào)用尚未完成,則EndInvoke會(huì)一直阻止調(diào)用線程,直到異步調(diào)用完成。

private delegate void ListenClientDelegate(out TcpClient client);

??????? /// <summary>接受掛起的客戶端連接請(qǐng)求</summary>

??????? private void ListenClient(out TcpClient newClient)

??????? {

??????????? try

??????????? {

??????????????? newClient = myListener.AcceptTcpClient();

??????????? }

??????????? catch

??????????? {

??????????????? newClient = null;

??????????? }

??????? }

/// <summary>監(jiān)聽客戶端請(qǐng)求</summary>

??????? private void ListenClientConnect()

??????? {

??????????? TcpClient newClient = null;

??????????? while (true)

??????????? {

??????????????? ListenClientDelegate d = new ListenClientDelegate(ListenClient);

??????????????? IAsyncResult result = d.BeginInvoke(out newClient, null, null);

??????????????? //使用輪詢方式來(lái)判斷異步操作是否完成

??????????????? while (result.IsCompleted == false)

??????????????? {

??????????????????? if (isExit)

??????????????????? {

??????????????????????? break;

??????????????????? }

??? ????????????????Thread.Sleep(250);

??????????????? }

??????????????? //獲取Begin方法的返回值和所有輸入/輸出參數(shù)

??????????????? d.EndInvoke(out newClient, result);

??????????????? if (newClient != null)

??????????????? {

??????????????????? //每接受一個(gè)客戶端連接,就創(chuàng)建一個(gè)對(duì)應(yīng)的線程循環(huán)接收該客戶端發(fā)來(lái)的信息

??????????????????? User user = new User(newClient);

??????????????????? Thread threadReceive = new Thread(ReceiveData);

??????????????????? threadReceive.Start(user);

??????????????????? userList.Add(user);

??????????????????? service.AddItem(string.Format("[{0}]進(jìn)入", newClient.Client.RemoteEndPoint));

??????????????????? service.AddItem(string.Format("當(dāng)前連接用戶數(shù):{0}", userList.Count));

??????????????? }

??????????????? else

??????????????? {

??????????????????? break;

??????????????? }

??????????? }

??? ????}

服務(wù)器端發(fā)送消息也類似上面的方法:

/// <summary>異步發(fā)送message給user</summary>

??????? public void AsyncSendToOne(User user, string message)

??????? {

??????????? SendToOneDelegate d = new SendToOneDelegate(SendToOne);

??????????? IAsyncResult result = d.BeginInvoke(user, message, null, null);

??????????? while (result.IsCompleted == false)

??????????? {

??????????????? Thread.Sleep(250);

??????????? }

??????????? d.EndInvoke(result);

??????? }

??????? public delegate void SendToOneDelegate(User user, string str);

?????? ?/// <summary>向某個(gè)客戶端發(fā)送信息</summary>

??????? /// <param name="gameTable">指定客戶</param>

??????? /// <param name="gameTable">信息</param>

??????? public void SendToOne(User user, string str)

??????? {

??????????? try

??????????? {

??????????????? user.sw.WriteLine(str);

??????????????? user.sw.Flush();

??????????????? AddItem(string.Format("向{0}發(fā)送{1}", user.userName, str));

??????????? }

??????????? catch

??????????? {

??????????????? AddItem(string.Format("向{0}發(fā)送信息失敗", user.userName));

??????????? }

??????? }

?

客戶端:用BackgroundWork組件實(shí)現(xiàn)異步編程功能

BackgroundWorker connectWork = new BackgroundWorker();

connectWork.DoWork += new DoWorkEventHandler(connectWork_DoWork);

????? connectWork.RunWorkerCompleted +=

??????????????? new RunWorkerCompletedEventHandler(connectWork_RunWorkerCompleted);

??????? /// <summary>異步方式與服務(wù)器進(jìn)行連接</summary>

??????? void connectWork_DoWork(object sender, DoWorkEventArgs e)

??????? {

??????????? client = new TcpClient();

??????????? //此處為方便演示,實(shí)際使用時(shí)要將Dns.GetHostName()改為服務(wù)器域名

??????????? IAsyncResult result = client.BeginConnect(Dns.GetHostName(), 51888, null, null);

??????????? while (result.IsCompleted == false)

??????????? {

??????????????? Thread.Sleep(100);

??????????? }

??????????? try

??????????? {

??????????????? client.EndConnect(result);

????? ??????????e.Result = "success";

??????????? }

??????????? catch (Exception ex)

??????????? {

??????????????? e.Result = ex.Message;

??????????????? return;

??????????? }

??????? }

??????? /// <summary>異步方式與服務(wù)器完成連接操作后的處理</summary>

??????? void connectWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

??????? {

??????????? if (e.Result.ToString() == "success")

??????????? {

??????????????? groupBox1.Visible = true;

??????????????? textBoxLocal.Text = client.Client.LocalEndPoint.ToString();

??????????????? textBoxServer.Text = client.Client.RemoteEndPoint.ToString();

??????????????? buttonConnect.Enabled = false;

??????????????? //獲取網(wǎng)絡(luò)流

??????????????? NetworkStream netStream = client.GetStream();

??????????????? //將網(wǎng)絡(luò)流作為二進(jìn)制讀寫對(duì)象

???????????? ???sr = new StreamReader(netStream, System.Text.Encoding.UTF8);

??????????????? sw = new StreamWriter(netStream, System.Text.Encoding.UTF8);

??????????????? service = new Service(listBox1, sw);

??????????????? service.SendToServer("Login," + textBoxName.Text.Trim());

??????????????? Thread threadReceive = new Thread(new ThreadStart(ReceiveData));

??????????????? threadReceive.IsBackground = true;

??????????????? threadReceive.Start();

??????????? }

??????????? else

??????????? {

??????????????? MessageBox.Show("與服務(wù)器連接失敗 "+e.Result, "",

?????????????????? MessageBoxButtons.OK, MessageBoxIcon.Information);

??????????????? buttonConnect.Enabled = true;

??????????? }

??????? }

??????? /// <summary>【登錄】按鈕的Click事件</summary>

??????? private void buttonConnect_Click(object sender, EventArgs e)

??????? {

??????????? buttonConnect.Enabled = false;

??????????? connectWork.RunWorkerAsync();

??????? }

接受消息的方法跟服務(wù)器端相同,不重復(fù)描述。

?

三、個(gè)人總結(jié)

???? 由于這個(gè)實(shí)驗(yàn)是參考書上已有的例子修改的,所以沒有出現(xiàn)之前無(wú)從下手的情況。在實(shí)驗(yàn)的過(guò)程中,遇到了一些問(wèn)題。首先,是輪流下子的問(wèn)題,不知道怎么通知對(duì)方。后來(lái)的解決方案是當(dāng)服務(wù)器端發(fā)送下子坐標(biāo)的時(shí)候同時(shí)更新同一桌玩家雙方的棋盤布局,只需要在特定棋盤上用turn變量斷定下棋的玩家。第二是邊界的判斷比較復(fù)雜,我采取了最笨的方法,每次下子的時(shí)候都是從新判斷整個(gè)棋盤的橫豎正斜反斜,這樣程序的運(yùn)行效率降低了。第三是同步改異步的問(wèn)題,。改成異步以后,一直在想,在Form中生成了一個(gè)Service類,那么終止條件是什么。請(qǐng)教了同學(xué)之后,發(fā)現(xiàn)其實(shí)在Form退出的時(shí)候,service就自動(dòng)消失了。通過(guò)本次試驗(yàn),我感覺受益匪淺。

轉(zhuǎn)載于:https://www.cnblogs.com/maomiyy/p/3762183.html

總結(jié)

以上是生活随笔為你收集整理的GOBang对战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。